br_danfe 0.11.2 → 0.12.0
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 +4 -4
- data/.gitignore +3 -1
- data/Gemfile.lock +31 -31
- data/br_danfe.gemspec +6 -5
- data/config/locales/pt-BR.yml +8 -0
- data/lib/br_danfe/danfe.rb +2 -2
- data/lib/br_danfe/danfe_lib/det_body.rb +1 -1
- data/lib/br_danfe/danfe_lib/document.rb +1 -1
- data/lib/br_danfe/danfe_lib/emit_header.rb +2 -2
- data/lib/br_danfe/danfe_lib/helper.rb +1 -27
- data/lib/br_danfe/danfe_lib/infadic.rb +1 -1
- data/lib/br_danfe/danfe_lib/xprod.rb +15 -15
- data/lib/br_danfe/danfe_nfce.rb +43 -0
- data/lib/br_danfe/danfe_nfce_lib/document.rb +35 -0
- data/lib/br_danfe/danfe_nfce_lib/footer.rb +15 -0
- data/lib/br_danfe/danfe_nfce_lib/header.rb +67 -0
- data/lib/br_danfe/danfe_nfce_lib/helper.rb +9 -0
- data/lib/br_danfe/danfe_nfce_lib/key.rb +18 -0
- data/lib/br_danfe/danfe_nfce_lib/nfce_identification.rb +20 -0
- data/lib/br_danfe/danfe_nfce_lib/product_list.rb +100 -0
- data/lib/br_danfe/danfe_nfce_lib/qr_code.rb +23 -0
- data/lib/br_danfe/danfe_nfce_lib/recipient.rb +72 -0
- data/lib/br_danfe/danfe_nfce_lib/total_list.rb +78 -0
- data/lib/br_danfe/helper.rb +29 -0
- data/lib/br_danfe/{danfe_lib/options.rb → logo_config.rb} +2 -2
- data/lib/br_danfe/{danfe_lib/logo_options.rb → logo_options.rb} +2 -2
- data/lib/br_danfe/version.rb +1 -1
- data/lib/br_danfe/xml.rb +36 -0
- data/spec/features/danfe_nfce_spec.rb +31 -0
- data/spec/fixtures/nfce/lib/document#render.pdf +99 -0
- data/spec/fixtures/nfce/lib/footer#render.pdf +74 -0
- data/spec/fixtures/nfce/lib/header#render-homologation.pdf +0 -0
- data/spec/fixtures/nfce/lib/header#render-long_name_with_logo.pdf +0 -0
- data/spec/fixtures/nfce/lib/header#render-long_name_without_logo.pdf +118 -0
- data/spec/fixtures/nfce/lib/header#render-short_name_with_logo.pdf +0 -0
- data/spec/fixtures/nfce/lib/header#render-short_name_without_logo.pdf +118 -0
- data/spec/fixtures/nfce/lib/key#render.pdf +104 -0
- data/spec/fixtures/nfce/lib/nfce_identification#render.pdf +118 -0
- data/spec/fixtures/nfce/lib/product_list#render-with_many_products.pdf +307 -0
- data/spec/fixtures/nfce/lib/product_list#render-with_many_products_and_long_names.pdf +335 -0
- data/spec/fixtures/nfce/lib/product_list#render-with_single_product.pdf +181 -0
- data/spec/fixtures/nfce/lib/product_list#render-with_single_product_and_long_name.pdf +195 -0
- data/spec/fixtures/nfce/lib/product_list_with_many_products.xml +367 -0
- data/spec/fixtures/nfce/lib/product_list_with_many_products_and_long_names.xml +367 -0
- data/spec/fixtures/nfce/lib/product_list_with_single_product.xml +238 -0
- data/spec/fixtures/nfce/lib/product_list_with_single_product_and_long_name.xml +238 -0
- data/spec/fixtures/nfce/lib/qr_code#render.pdf +0 -0
- data/spec/fixtures/nfce/lib/recipient#render-company.pdf +95 -0
- data/spec/fixtures/nfce/lib/recipient#render-consumer_without_document.pdf +88 -0
- data/spec/fixtures/nfce/lib/recipient#render-foreign.pdf +95 -0
- data/spec/fixtures/nfce/lib/recipient#render-individual.pdf +95 -0
- data/spec/fixtures/nfce/lib/recipient#render-unidentified_consumer.pdf +81 -0
- data/spec/fixtures/nfce/lib/total_list#does_not_render-payment_methods.pdf +139 -0
- data/spec/fixtures/nfce/lib/total_list#render-grouped_payment_methods.pdf +188 -0
- data/spec/fixtures/nfce/lib/total_list#render-totals.pdf +139 -0
- data/spec/fixtures/nfce/lib/total_list#render-without_payment.pdf +202 -0
- data/spec/fixtures/nfce/lib/total_list#render.pdf +202 -0
- data/spec/fixtures/nfce/v4.00/nfce.xml +367 -0
- data/spec/fixtures/nfce/v4.00/rendered_nfce.fixture.pdf +0 -0
- data/spec/fixtures/nfce/v4.00/saved_nfce.fixture.pdf +0 -0
- data/spec/lib/danfe_lib/dest_spec.rb +1 -1
- data/spec/lib/danfe_lib/det_body_spec.rb +1 -1
- data/spec/lib/danfe_lib/document_spec.rb +1 -1
- data/spec/lib/danfe_lib/dup_spec.rb +1 -1
- data/spec/lib/danfe_lib/emit_header_spec.rb +1 -1
- data/spec/lib/danfe_lib/helper_spec.rb +0 -54
- data/spec/lib/danfe_lib/icmstot_spec.rb +1 -1
- data/spec/lib/danfe_lib/infadic_spec.rb +1 -1
- data/spec/lib/danfe_lib/infadic_vol_spec.rb +1 -1
- data/spec/lib/danfe_lib/issqn_spec.rb +1 -1
- data/spec/lib/danfe_lib/ticket_spec.rb +1 -1
- data/spec/lib/danfe_lib/transp_spec.rb +1 -1
- data/spec/lib/danfe_lib/vol_spec.rb +1 -1
- data/spec/lib/danfe_nfce_lib/document_spec.rb +19 -0
- data/spec/lib/danfe_nfce_lib/footer_spec.rb +42 -0
- data/spec/lib/danfe_nfce_lib/header_spec.rb +117 -0
- data/spec/lib/danfe_nfce_lib/helper_spec.rb +28 -0
- data/spec/lib/danfe_nfce_lib/key_spec.rb +45 -0
- data/spec/lib/danfe_nfce_lib/nfce_identification_spec.rb +48 -0
- data/spec/lib/danfe_nfce_lib/product_list_spec.rb +66 -0
- data/spec/lib/danfe_nfce_lib/qr_code_spec.rb +35 -0
- data/spec/lib/danfe_nfce_lib/recipient_spec.rb +163 -0
- data/spec/lib/danfe_nfce_lib/total_list_spec.rb +188 -0
- data/spec/lib/helper_spec.rb +102 -0
- data/spec/lib/logo_config_spec.rb +21 -0
- data/spec/lib/{danfe_lib/logo_options_spec.rb → logo_options_spec.rb} +8 -22
- data/spec/lib/{danfe_lib/xml_spec.rb → xml_spec.rb} +2 -2
- metadata +87 -18
- data/lib/br_danfe/danfe_lib/xml.rb +0 -38
- data/spec/lib/danfe_lib/options_spec.rb +0 -17
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class Helper
|
|
4
|
+
def self.address(ender_tag)
|
|
5
|
+
"#{ender_tag.css('xLgr').text}, #{ender_tag.css('nro').text}, #{ender_tag.css('xBairro').text}, #{ender_tag.css('xMun').text} - #{ender_tag.css('UF').text}"
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class Key
|
|
4
|
+
def initialize(pdf, xml)
|
|
5
|
+
@pdf = pdf
|
|
6
|
+
@xml = xml
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def render
|
|
10
|
+
@pdf.render_blank_line
|
|
11
|
+
|
|
12
|
+
@pdf.text 'Consulte pela Chave de Acesso em', size: 7, align: :center, style: :bold
|
|
13
|
+
@pdf.text @xml['urlChave'], size: 7, align: :center
|
|
14
|
+
@pdf.text @xml['chNFe'].gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, '\\1 '), size: 6, align: :center
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class NfceIdentification
|
|
4
|
+
def initialize(pdf, xml)
|
|
5
|
+
@pdf = pdf
|
|
6
|
+
@xml = xml
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def render
|
|
10
|
+
emitted_at = BrDanfe::Helper.format_datetime(@xml['ide/dhEmi'])
|
|
11
|
+
identification = "NFC-e nº #{@xml['ide/nNF']} Série #{@xml['ide/serie']} #{emitted_at}"
|
|
12
|
+
|
|
13
|
+
@pdf.render_blank_line
|
|
14
|
+
@pdf.text identification, size: 7, align: :center, style: :bold
|
|
15
|
+
@pdf.text "<b>Protocolo de autorização:</b> #{@xml['infProt/nProt']}", size: 7, align: :center, inline_format: true
|
|
16
|
+
@pdf.text "<b>Data de autorização: </b> #{BrDanfe::Helper.format_datetime(@xml['infProt/dhRecbto'])}", size: 7, align: :center, inline_format: true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class ProductList
|
|
4
|
+
def initialize(pdf, xml)
|
|
5
|
+
@pdf = pdf
|
|
6
|
+
@xml = xml
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def render
|
|
10
|
+
render_headers(headers)
|
|
11
|
+
render_products(products)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def headers
|
|
17
|
+
[
|
|
18
|
+
header_column('Código', :left),
|
|
19
|
+
header_column('Descrição', :left),
|
|
20
|
+
header_column('Qtde', :right),
|
|
21
|
+
header_column('UN', :right),
|
|
22
|
+
header_column('Vl Unit', :right),
|
|
23
|
+
header_column('Vl Total', :right)
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def header_column(title, align)
|
|
28
|
+
{ content: title, options: { align: align, size: 6, style: :bold } }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def products
|
|
32
|
+
@xml.collect('xmlns', 'det') { |det| product(det) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def product(det)
|
|
36
|
+
[
|
|
37
|
+
cell_text(det.css('prod/cProd').text),
|
|
38
|
+
cell_text(det.css('prod/xProd').text),
|
|
39
|
+
cell_number(BrDanfe::Helper.numerify(det.css('prod/qCom').text)),
|
|
40
|
+
cell_text(det.css('prod/uCom').text, { align: :right }),
|
|
41
|
+
cell_number(BrDanfe::Helper.numerify(det.css('prod/vUnCom').text)),
|
|
42
|
+
cell_number(BrDanfe::Helper.numerify(det.css('prod/vProd').text))
|
|
43
|
+
]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def cell_text(text, options = {})
|
|
47
|
+
cell = { content: text, options: { border_width: 0, size: 6 } }
|
|
48
|
+
cell[:options].merge!(options)
|
|
49
|
+
cell
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cell_number(text)
|
|
53
|
+
cell_text(text, { align: :right })
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def columns
|
|
57
|
+
[
|
|
58
|
+
{ width: 0.9.cm, position: 0 },
|
|
59
|
+
{ width: 2.6.cm, position: 0.9.cm },
|
|
60
|
+
{ width: 1.1.cm, position: 3.5.cm },
|
|
61
|
+
{ width: 0.4.cm, position: 4.6.cm },
|
|
62
|
+
{ width: 1.2.cm, position: 5.cm },
|
|
63
|
+
{ width: 1.2.cm, position: 6.2.cm }
|
|
64
|
+
]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def render_headers(headers)
|
|
68
|
+
2.times { @pdf.render_blank_line }
|
|
69
|
+
cursor = @pdf.cursor
|
|
70
|
+
headers.each_with_index do |header, index|
|
|
71
|
+
@pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: 0.2.cm do
|
|
72
|
+
@pdf.text header[:content], header[:options]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def render_products(products)
|
|
78
|
+
@pdf.render_blank_line
|
|
79
|
+
index_of_product_name = 1
|
|
80
|
+
products.each do |product|
|
|
81
|
+
box_height = box_height(product[index_of_product_name][:content])
|
|
82
|
+
cursor = @pdf.cursor
|
|
83
|
+
|
|
84
|
+
product.each_with_index do |product, index|
|
|
85
|
+
@pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: box_height do
|
|
86
|
+
@pdf.text product[:content], product[:options]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def box_height(content)
|
|
93
|
+
line_height_base = 0.23.cm
|
|
94
|
+
|
|
95
|
+
lines = content.scan(/[\s\S]{1,20}( |$)/).length
|
|
96
|
+
line_height_base * lines
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class QrCode
|
|
4
|
+
require 'rqrcode'
|
|
5
|
+
require 'chunky_png'
|
|
6
|
+
require 'tempfile'
|
|
7
|
+
|
|
8
|
+
def initialize(pdf, xml)
|
|
9
|
+
@pdf = pdf
|
|
10
|
+
@xml = xml
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render
|
|
14
|
+
qrcode = RQRCode::QRCode.new(@xml['qrCode'])
|
|
15
|
+
image = Tempfile.create('qrcode.png')
|
|
16
|
+
image.write(qrcode.as_png(module_px_size: 12).to_s)
|
|
17
|
+
|
|
18
|
+
box_size = 3.cm
|
|
19
|
+
@pdf.image image, { width: box_size, height: box_size, position: :center }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class Recipient
|
|
4
|
+
def initialize(pdf, xml)
|
|
5
|
+
@pdf = pdf
|
|
6
|
+
@xml = xml
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def render
|
|
10
|
+
@pdf.render_blank_line
|
|
11
|
+
|
|
12
|
+
if identified_recipient?
|
|
13
|
+
render_document
|
|
14
|
+
|
|
15
|
+
@pdf.text @xml['dest/xNome'], options
|
|
16
|
+
@pdf.text BrDanfe::DanfeNfceLib::Helper.address(@xml.css('enderDest')), options
|
|
17
|
+
else
|
|
18
|
+
@pdf.text 'CONSUMIDOR NÃO IDENTIFICADO', options
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def options
|
|
25
|
+
{ size: 7, align: :center }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def identified_recipient?
|
|
29
|
+
@xml['dest/xNome'].present?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def render_document
|
|
33
|
+
document_text = document
|
|
34
|
+
|
|
35
|
+
@pdf.text document_text, options if document_text.present?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def document
|
|
39
|
+
return company if company?
|
|
40
|
+
return individual if individual?
|
|
41
|
+
return foreign if foreign?
|
|
42
|
+
return ''
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def company?
|
|
46
|
+
@xml['dest/CNPJ'].present?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def company
|
|
50
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new @xml['dest/CNPJ']
|
|
51
|
+
"CONSUMIDOR CNPJ: #{cnpj.formatted}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def individual?
|
|
55
|
+
@xml['dest/CPF'].present?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def individual
|
|
59
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(@xml['dest/CPF'])
|
|
60
|
+
"CONSUMIDOR CPF: #{cpf.formatted}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def foreign?
|
|
64
|
+
@xml['dest/idEstrangeiro'].present?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def foreign
|
|
68
|
+
"CONSUMIDOR Id. Estrangeiro: #{@xml['dest/idEstrangeiro']}"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
module DanfeNfceLib
|
|
3
|
+
class TotalList
|
|
4
|
+
require 'bigdecimal'
|
|
5
|
+
|
|
6
|
+
def initialize(pdf, xml)
|
|
7
|
+
@pdf = pdf
|
|
8
|
+
@xml = xml
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def render
|
|
12
|
+
subtotal
|
|
13
|
+
totals
|
|
14
|
+
payment_methods
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def subtotal
|
|
20
|
+
cursor = @pdf.cursor
|
|
21
|
+
@pdf.bounding_box [4.8.cm, cursor], width: 1.4.cm, height: 0.2.cm do
|
|
22
|
+
@pdf.text 'Subtotal R$', { size: 6, align: :left }
|
|
23
|
+
end
|
|
24
|
+
@pdf.bounding_box [6.2.cm, cursor], width: 1.2.cm, height: 0.2.cm do
|
|
25
|
+
@pdf.text BrDanfe::Helper.numerify(@xml['ICMSTot > vProd'].to_f), { size: 6, align: :right }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def totals
|
|
30
|
+
@pdf.render_blank_line
|
|
31
|
+
|
|
32
|
+
cursor = @pdf.cursor
|
|
33
|
+
print_text('Qtde. total de itens', cursor, { size: 7, align: :left })
|
|
34
|
+
print_text(@xml.css('det').count.to_s, cursor, { size: 7, align: :right })
|
|
35
|
+
|
|
36
|
+
cursor = @pdf.cursor
|
|
37
|
+
print_text('Desconto R$', cursor, { size: 7, align: :left})
|
|
38
|
+
print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vDesc'].to_f), cursor, { size: 7, align: :right })
|
|
39
|
+
|
|
40
|
+
cursor = @pdf.cursor
|
|
41
|
+
print_text('Valor Total R$', cursor, { size: 7, align: :left, style: :bold })
|
|
42
|
+
print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vNF'].to_f), cursor, { size: 7, align: :right, style: :bold })
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def payment_methods
|
|
46
|
+
payments = {}
|
|
47
|
+
without_payment = '90'
|
|
48
|
+
|
|
49
|
+
@xml.css('detPag').each do |detPag|
|
|
50
|
+
next if detPag.css('tPag').text == without_payment
|
|
51
|
+
payments[detPag.css('tPag').text] ||= BigDecimal('0')
|
|
52
|
+
actual_payment_value = BigDecimal(detPag.css('vPag').text)
|
|
53
|
+
payments[detPag.css('tPag').text] += actual_payment_value
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if payments.present?
|
|
57
|
+
@pdf.render_blank_line
|
|
58
|
+
|
|
59
|
+
cursor = @pdf.cursor
|
|
60
|
+
print_text('Forma de pagamento', cursor, { size: 7, align: :left, style: :bold })
|
|
61
|
+
print_text('Valor pago R$', cursor, { size: 7, align: :right, style: :bold })
|
|
62
|
+
|
|
63
|
+
payments.each do |key, value|
|
|
64
|
+
cursor = @pdf.cursor
|
|
65
|
+
print_text(I18n.t("nfce.payment_methods.#{key}"), cursor, { size: 7, align: :left })
|
|
66
|
+
print_text(BrDanfe::Helper.numerify(value.to_f), cursor, { size: 7, align: :right })
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def print_text(text, cursor, options)
|
|
72
|
+
@pdf.bounding_box [0, cursor], width: 7.4.cm, height: 0.25.cm do
|
|
73
|
+
@pdf.text text, options
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
class Helper
|
|
3
|
+
def self.homologation?(xml)
|
|
4
|
+
xml.css('nfeProc/NFe/infNFe/ide/tpAmb').text == '2'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.numerify(number)
|
|
8
|
+
return '' if !number || number == ''
|
|
9
|
+
|
|
10
|
+
separated_number = number.to_s.split('.')
|
|
11
|
+
integer_part = separated_number[0].reverse.gsub(/\d{3}(?=\d)/, '\&.').reverse
|
|
12
|
+
decimal_part = separated_number[1] || '00'
|
|
13
|
+
decimal_part += '0' if decimal_part.size < 2
|
|
14
|
+
|
|
15
|
+
integer_part + ',' + decimal_part
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.format_datetime(xml_datetime)
|
|
19
|
+
formated = ''
|
|
20
|
+
|
|
21
|
+
unless xml_datetime.empty?
|
|
22
|
+
date = DateTime.strptime(xml_datetime, '%Y-%m-%dT%H:%M:%S')
|
|
23
|
+
formated = date.strftime('%d/%m/%Y %H:%M:%S')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
formated
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/br_danfe/version.rb
CHANGED
data/lib/br_danfe/xml.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module BrDanfe
|
|
2
|
+
class XML
|
|
3
|
+
def css(xpath)
|
|
4
|
+
@xml.css(xpath)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def initialize(xml)
|
|
8
|
+
@xml = Nokogiri::XML(xml)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def [](xpath)
|
|
12
|
+
node = @xml.css(xpath)
|
|
13
|
+
node ? node.text : ''
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def collect(ns, tag)
|
|
17
|
+
result = []
|
|
18
|
+
# With namespace
|
|
19
|
+
begin
|
|
20
|
+
@xml.xpath("//#{ns}:#{tag}").each do |det|
|
|
21
|
+
result << yield(det)
|
|
22
|
+
end
|
|
23
|
+
rescue StandardError
|
|
24
|
+
# Without namespace
|
|
25
|
+
@xml.xpath("//#{tag}").each do |det|
|
|
26
|
+
result << yield(det)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def version_is_310_or_newer?
|
|
33
|
+
@xml.css('infNFe').attr('versao').to_s.to_f >= 3.10
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe BrDanfe::DanfeNfce do
|
|
4
|
+
let(:output_pdf) { "#{base_dir}output.pdf" }
|
|
5
|
+
let(:base_dir) { './spec/fixtures/nfce/v4.00/' }
|
|
6
|
+
let(:danfe) { BrDanfe::DanfeNfce.new(File.read("#{base_dir}nfce.xml")) }
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
danfe.options.logo = 'spec/fixtures/logo.png'
|
|
10
|
+
danfe.options.logo_dimensions = { width: 100, height: 100 }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '#render_pdf' do
|
|
14
|
+
it 'renders the NFC-e pdf' do
|
|
15
|
+
expected = IO.binread("#{base_dir}rendered_nfce.fixture.pdf")
|
|
16
|
+
expect(danfe.render_pdf).to eq expected
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#save_pdf' do
|
|
21
|
+
before { File.delete(output_pdf) if File.exist?(output_pdf) }
|
|
22
|
+
after { File.delete(output_pdf) if File.exist?(output_pdf) }
|
|
23
|
+
|
|
24
|
+
it 'saves the NFC-e as pdf' do
|
|
25
|
+
expect(File.exist?(output_pdf)).to be_falsey
|
|
26
|
+
danfe.save_pdf output_pdf
|
|
27
|
+
|
|
28
|
+
expect("#{base_dir}saved_nfce.fixture.pdf").to have_same_content_of file: output_pdf
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|