br_danfe 0.0.1 → 0.0.2

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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- N2U5NDM0ZjY5YWVmMGFjYjk2M2JhZGE3NzBjNDcyODc0ZjcxYmQyNg==
5
- data.tar.gz: !binary |-
6
- MTJkNDIyMWMzYWJjMjVlNzQ0ODdmNmZlZDI4MDM5OWM2MTQ1NDQ0Mg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NThlMmQ2NmMxZjQ3NDgxYzkzNzU2MjkwMTE3MDE0OWE3M2Q1NzU3YzAzNThh
10
- YmFhMjEyZDVjOTQzMzQ1NzY5NDQ0ZjgxMDQzNDg5NzdlNGFhMmE1OGIyYjFl
11
- MmJkNTMxYzAyMzM2YWUzMWZhYTI3MWQ1ZDU1N2FkYjY0MjA4ZjY=
12
- data.tar.gz: !binary |-
13
- MzljOWMyYTQ4YjIzMjM5M2YzNTczZjgyZTE1YmIwYmE5MDA2NTZiN2YzMGY1
14
- NjY2NTQ5ZDhjODlmNmZjYzM0NDM4MDE2ZDY4ODczMjQ2NGRiZjEwNWMxY2Nh
15
- NWQ5ODRmNjVlNGNjZjViYTZiNzI5ZTE2MzA3YjlhNTYzZTQwZjE=
2
+ SHA1:
3
+ metadata.gz: 020747659bc373a796e74e5a10933a74a9f45b6d
4
+ data.tar.gz: ae11def5625f8fef1862e7098d4854979c3f6e9b
5
+ SHA512:
6
+ metadata.gz: d2496b9f7bc5a77e72f3151cc91bb2ed628f348a55ae501b121a1747b8ea60f445a370c17575a0094e2cb14848618f9d4ee99d0353c5fdbbda20b302c7e42a75
7
+ data.tar.gz: 9069fa0a81380ae5d2db266128e29f43ceaede10cdca8e80343207fe6c59bb8e5e1e810a676295f744c2bb9f0a5372af392d3809951eaf09e2c064144b0102ae
data/README.md CHANGED
@@ -6,26 +6,17 @@ This gem generates PDF files for Brazilian DANFE (_Documento Auxiliar da Nota Fi
6
6
 
7
7
  This gem requires `ruby >= 1.9.x`.
8
8
 
9
- It's a fork of [Ruby DANFE](http://github.com/taxweb/ruby_danfe) project.
10
-
11
- The difference is that this project doesn't support DACTE (_Documento Auxiliar do Conhecimento de Transporte Eletrônico_) or NFC-e (_Nota Fiscal do Consumidor Eletrônica_). It's only focused on DANFE.
12
-
13
9
  ## Installing
14
10
 
15
11
  gem install ruby_danfe
16
12
 
17
13
  ## Usage
18
14
 
19
- If you have the xml saved in a file:
20
-
21
- require "br_danfe"
22
- BrDanfe.generate("sample.pdf", "sample.xml")
15
+ xml = File.read("nfe.xml")
23
16
 
24
- If you have the xml in a variable:
25
-
26
- xml = BrDanfe::XML.new(my_xml_string)
27
- pdf = BrDanfe.generatePDF(xml)
28
- pdf.render_file "output.pdf"
17
+ danfe = BrDanfe::Danfe.new(xml)
18
+ danfe.options.logo_path = "logo.png"
19
+ danfe.save_pdf("nfe.pdf")
29
20
 
30
21
  ## I18n
31
22
 
@@ -51,27 +42,14 @@ You can use it following the steps above:
51
42
 
52
43
  You can also use an special version of irb with all classes pre-loaded. Just use:
53
44
 
54
- $ rake console
55
- I18n.locale = "pt-BR"
56
- BrDanfe.generate("output.pdf", "test/nfe_with_ns.xml")
57
-
58
- or
59
-
60
45
  $ rake console
61
46
 
62
47
  I18n.locale = "pt-BR"
63
48
 
64
- my_xml_string = ""
65
- file = File.new("test/nfe_with_ns.xml", "r")
66
- while (line = file.gets)
67
- my_xml_string = my_xml_string + line
68
- end
69
- file.close
70
-
71
- xml = BrDanfe::XML.new(my_xml_string)
72
- pdf = BrDanfe.generatePDF(xml)
49
+ xml = File.read "test/nfe_with_ns.xml"
73
50
 
74
- pdf.render_file "output.pdf"
51
+ danfe = BrDanfe::Danfe.new(xml)
52
+ danfe.save_pdf "output.pdf"
75
53
 
76
54
  #### Automated tests with RSpec
77
55
 
@@ -111,6 +89,10 @@ We encourage you to contribute to BrDanfe!
111
89
  4. Push to the branch (`git push origin my-new-feature`)
112
90
  5. Create new Pull Request
113
91
 
92
+ ## Ruby DANFE gem
93
+
94
+ This project is based on [Ruby DANFE gem](http://github.com/taxweb/ruby_danfe).
95
+
114
96
  ## License
115
97
 
116
98
  BrDanfe is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -32,6 +32,13 @@ namespace :spec do
32
32
  task :recreate_pdfs do
33
33
  Dir["spec/fixtures/nfe*.xml"].each do |f|
34
34
  puts "Recreating #{f}.fixture.pdf"
35
+
36
+ if File.exist?("#{f}.logo.png")
37
+ BrDanfe.options.logo_path = "#{f}.logo.png"
38
+ else
39
+ BrDanfe.options.logo_path = ""
40
+ end
41
+
35
42
  BrDanfe.generate("#{f}.fixture.pdf", "#{f}")
36
43
  end
37
44
  end
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "pry"
25
25
  spec.add_development_dependency "rspec"
26
26
  spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "codeclimate-test-reporter"
27
28
  end
@@ -3,7 +3,7 @@ pt-BR:
3
3
  chNFe: "CHAVE DE ACESSO"
4
4
  infProt: "PROTOCOLO DE AUTORIZAÇÃO DE USO"
5
5
  others:
6
- without_fiscal_value: "SEM VALOR FISCAL"
6
+ has_no_fiscal_value: "SEM VALOR FISCAL"
7
7
  page: "FOLHA %{current} de %{total}"
8
8
  danfe: "DOCUMENTO AUXILIAR DA NOTA FISCAL ELETRÔNICA"
9
9
  sefaz: "Consulta de autenticidade no portal nacional da NF-e www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizadora"
@@ -0,0 +1,64 @@
1
+ module BrDanfe
2
+ class Danfe
3
+ attr_reader :options
4
+
5
+ def initialize(xml)
6
+ @xml = XML.new(xml)
7
+ @pdf = Document.new
8
+ @options = Options.new
9
+
10
+ create_watermark
11
+ end
12
+
13
+ def save_pdf(filename)
14
+ generate
15
+ @pdf.render_file filename
16
+ end
17
+
18
+ private
19
+ def create_watermark
20
+ @pdf.create_stamp("has_no_fiscal_value") do
21
+ @pdf.fill_color "7d7d7d"
22
+ @pdf.text_box I18n.t("danfe.others.has_no_fiscal_value"),
23
+ size: 2.2.cm,
24
+ width: @pdf.bounds.width,
25
+ height: @pdf.bounds.height,
26
+ align: :center,
27
+ valign: :center,
28
+ at: [0, @pdf.bounds.height],
29
+ rotate: 45,
30
+ rotate_around: :center
31
+ end
32
+ end
33
+
34
+ def generate
35
+ @pdf.stamp("has_no_fiscal_value") if Helper.has_no_fiscal_value?(@xml)
36
+
37
+ @pdf.repeat(:all) { repeat_on_each_page }
38
+
39
+ DetBody.new(@pdf, @xml).render
40
+
41
+ @pdf.page_count.times do |i|
42
+ @pdf.go_to_page(i + 1)
43
+ @pdf.ibox 1.00, 2.08, 8.71, 5.54, "",
44
+ I18n.t("danfe.others.page", current: i+1, total: @pdf.page_count),
45
+ { size: 8, align: :center, valign: :center, border: 0, style: :bold }
46
+ end
47
+
48
+ @pdf
49
+ end
50
+
51
+ def repeat_on_each_page
52
+ Ticket.render(@pdf, @xml)
53
+ Emit.new(@pdf, @xml, @options.logo_path).render
54
+ Dest.new(@pdf, @xml).render
55
+ Dup.new(@pdf, @xml).render
56
+ Icmstot.render(@pdf, @xml)
57
+ Transp.render(@pdf, @xml)
58
+ nVol = Vol.new(@pdf, @xml).render
59
+ DetHeader.new(@pdf, @xml).render
60
+ Issqn.render(@pdf, @xml)
61
+ Infadic.new(@pdf, @xml).render(nVol)
62
+ end
63
+ end
64
+ end
@@ -1,21 +1,70 @@
1
1
  module BrDanfe
2
2
  class Dest
3
- def self.render(pdf, xml)
4
- pdf.ititle 0.42, 10.00, 0.25, 8.16, "dest.title"
5
-
6
- pdf.lbox 0.85, 12.32, 0.25, 8.58, xml, "dest/xNome"
7
- pdf.ibox 0.85, 5.33, 12.57, 8.58, I18n.t("danfe.dest.CNPJ"), Cnpj.format(xml["dest/CNPJ"]) if xml["dest/CNPJ"] != ""
8
- pdf.ibox 0.85, 5.33, 12.57, 8.58, I18n.t("danfe.dest.CPF"), Cpf.format(xml["dest/CPF"]) if xml["dest/CPF"] != ""
9
- pdf.idate 0.85, 2.92, 17.90, 8.58, "ide.dEmi", xml["ide/dEmi"], {align: :right}
10
- pdf.ibox 0.85, 10.16, 0.25, 9.43, I18n.t("danfe.enderDest.xLgr"), xml["enderDest/xLgr"] + " " + xml["enderDest/nro"]
11
- pdf.lbox 0.85, 4.83, 10.41, 9.43, xml, "enderDest/xBairro"
12
- pdf.ibox 0.85, 2.67, 15.24, 9.43, I18n.t("danfe.enderDest.CEP"), Cep.format(xml["enderDest/CEP"])
13
- pdf.idate 0.85, 2.92, 17.90, 9.43, "ide.dSaiEnt", xml["ide/dSaiEnt"], {align: :right}
14
- pdf.lbox 0.85, 7.11, 0.25, 10.28, xml, "enderDest/xMun"
15
- pdf.ibox 0.85, 4.06, 7.36, 10.28, I18n.t("danfe.enderDest.fone"), Phone.format(xml["enderDest/fone"])
16
- pdf.lbox 0.85, 1.14, 11.42, 10.28, xml, "enderDest/UF"
17
- pdf.ibox 0.85, 5.33, 12.56, 10.28, I18n.t("danfe.dest.IE"), Ie.format(xml["dest/IE"], xml["enderDest/UF"])
18
- pdf.idate 0.85, 2.92, 17.90, 10.28, "ide.hSaiEnt", xml["ide/dSaiEnt"], {align: :right}
3
+ def initialize(pdf, xml)
4
+ @pdf = pdf
5
+ @xml = xml
6
+ end
7
+
8
+ def render
9
+ @pdf.ititle 0.42, 10.00, 0.25, 8.16, "dest.title"
10
+
11
+ render_line1
12
+ render_line2
13
+ render_line3
14
+ end
15
+
16
+ private
17
+ def render_line1
18
+ @pdf.lbox 0.85, 12.32, 0.25, 8.58, @xml, "dest/xNome"
19
+ render_cnpj_cpf
20
+ @pdf.idate 0.85, 2.92, 17.90, 8.58, "ide.dEmi", @xml["ide/dEmi"], { align: :right }
21
+ end
22
+
23
+ def render_cnpj_cpf
24
+ if @xml["dest/CNPJ"] == ""
25
+ @pdf.ibox 0.85, 5.33, 12.57, 8.58, I18n.t("danfe.dest.CPF"), cpf
26
+ else
27
+ @pdf.ibox 0.85, 5.33, 12.57, 8.58, I18n.t("danfe.dest.CNPJ"), cnpj
28
+ end
29
+ end
30
+
31
+ def cnpj
32
+ Cnpj.format(@xml["dest/CNPJ"])
33
+ end
34
+
35
+ def cpf
36
+ Cpf.format(@xml["dest/CPF"])
37
+ end
38
+
39
+ def render_line2
40
+ @pdf.ibox 0.85, 10.16, 0.25, 9.43, I18n.t("danfe.enderDest.xLgr"), street
41
+ @pdf.lbox 0.85, 4.83, 10.41, 9.43, @xml, "enderDest/xBairro"
42
+ @pdf.ibox 0.85, 2.67, 15.24, 9.43, I18n.t("danfe.enderDest.CEP"), cep
43
+ @pdf.idate 0.85, 2.92, 17.90, 9.43, "ide.dSaiEnt", @xml["ide/dSaiEnt"], { align: :right }
44
+ end
45
+
46
+ def street
47
+ @xml["enderDest/xLgr"] + " " + @xml["enderDest/nro"]
48
+ end
49
+
50
+ def cep
51
+ Cep.format(@xml["enderDest/CEP"])
52
+ end
53
+
54
+ def render_line3
55
+ @pdf.lbox 0.85, 7.11, 0.25, 10.28, @xml, "enderDest/xMun"
56
+ @pdf.ibox 0.85, 4.06, 7.36, 10.28, I18n.t("danfe.enderDest.fone"), phone
57
+ @pdf.lbox 0.85, 1.14, 11.42, 10.28, @xml, "enderDest/UF"
58
+ @pdf.ibox 0.85, 5.33, 12.56, 10.28, I18n.t("danfe.dest.IE"), ie
59
+ @pdf.idate 0.85, 2.92, 17.90, 10.28, "ide.hSaiEnt", @xml["ide/dSaiEnt"], { align: :right }
60
+ end
61
+
62
+ def phone
63
+ Phone.format(@xml["enderDest/fone"])
64
+ end
65
+
66
+ def ie
67
+ Ie.format(@xml["dest/IE"], @xml["enderDest/UF"])
19
68
  end
20
69
  end
21
70
  end
@@ -0,0 +1,68 @@
1
+ module BrDanfe
2
+ class DetBody
3
+ def initialize(pdf, xml)
4
+ @pdf = pdf
5
+ @xml = xml
6
+ end
7
+
8
+ def render
9
+ @pdf.font_size(6) do
10
+ @pdf.itable 6.37, 21.50, 0.25, 18.17,
11
+ products,
12
+ column_widths: column_widths,
13
+ cell_style: {padding: 2, border_width: 0} do |table|
14
+ table.column(6..13).style(align: :right)
15
+ table.column(0..13).border_width = 1
16
+ table.column(0..13).borders = [:bottom]
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+ def products
23
+ @xml.collect("xmlns", "det") { |det| product(det) }
24
+ end
25
+
26
+ def product(det)
27
+ [
28
+ det.css("prod/cProd").text,
29
+ Xprod.new(det).render,
30
+ det.css("prod/NCM").text,
31
+ Cst.to_danfe(det),
32
+ det.css("prod/CFOP").text,
33
+ det.css("prod/uCom").text,
34
+ numerify(det, "prod/qCom"),
35
+ numerify(det, "prod/vUnCom"),
36
+ numerify(det, "prod/vProd"),
37
+ numerify(det, "ICMS/*/vBC"),
38
+ numerify(det, "ICMS/*/vICMS"),
39
+ numerify(det, "IPI/*/vIPI"),
40
+ numerify(det, "ICMS/*/pICMS"),
41
+ numerify(det, "IPI/*/pIPI")
42
+ ]
43
+ end
44
+
45
+ def numerify(det, xpath)
46
+ Helper.numerify(det.css("#{xpath}").text)
47
+ end
48
+
49
+ def column_widths
50
+ {
51
+ 0 => 2.00.cm,
52
+ 1 => 4.90.cm,
53
+ 2 => 1.30.cm,
54
+ 3 => 0.80.cm,
55
+ 4 => 1.00.cm,
56
+ 5 => 1.00.cm,
57
+ 6 => 1.30.cm,
58
+ 7 => 1.50.cm,
59
+ 8 => 1.50.cm,
60
+ 9 => 1.50.cm,
61
+ 10 => 1.00.cm,
62
+ 11 => 1.00.cm,
63
+ 12 => 0.90.cm,
64
+ 13 => 0.86.cm
65
+ }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ module BrDanfe
2
+ class DetHeader
3
+ def initialize(pdf, xml)
4
+ @pdf = pdf
5
+ @xml = xml
6
+ end
7
+
8
+ def render
9
+ @pdf.ititle 0.42, 10.00, 0.25, 17.45, "det.title"
10
+
11
+ column(2.00, 0.25, "prod.cProd")
12
+ column(4.90, 2.25, "prod.xProd")
13
+ column(1.30, 7.15, "prod.NCM")
14
+ column(0.80, 8.45, "ICMS.CST")
15
+ column(1.00, 9.25, "prod.CFOP")
16
+ column(1.00, 10.25, "prod.uCom")
17
+ column(1.30, 11.25, "prod.qCom")
18
+ column(1.50, 12.55, "prod.vUnCom")
19
+ column(1.50, 14.05, "prod.vProd")
20
+ column(1.50, 15.55, "ICMS.vBC")
21
+ column(1.00, 17.05, "ICMS.vICMS")
22
+ column(1.00, 18.05, "IPI.vIPI")
23
+ column(0.90, 19.05, "ICMS.pICMS")
24
+ column(0.86, 19.95, "IPI.pIPI")
25
+
26
+ @pdf.horizontal_line 0.25.cm, 20.83.cm, at: Helper.invert(18.17.cm)
27
+ end
28
+
29
+ private
30
+ def column(w, x, title)
31
+ @pdf.ibox 6.70, w, x, 17.87, I18n.t("danfe.det.#{title}")
32
+ end
33
+ end
34
+ end
@@ -17,10 +17,6 @@ module BrDanfe
17
17
  @document.send(method_name, *args, &block)
18
18
  end
19
19
 
20
- def respond_to_missing?(method_name, include_private = false)
21
- @document.respond_to?(method_name, include_private) || super
22
- end
23
-
24
20
  def ititle(h, w, x, y, i18n)
25
21
  title = ""
26
22
  title = I18n.t("danfe.#{i18n}") if i18n != ""
@@ -96,8 +92,18 @@ module BrDanfe
96
92
  }.merge(options)
97
93
 
98
94
  self.stroke_rectangle at, w, h if options[:border] == 1
99
- self.text_box title, size: 6, style: :italic, at: [at[0] + 2, at[1] - 2], width: w - 4, height: 8 if title != ""
100
- 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]
95
+
96
+ at[0] += 2
97
+
98
+ if title != ""
99
+ title_coord = Array.new(at)
100
+ title_coord[1] -= 2
101
+ self.text_box title, size: 6, style: :italic, at: title_coord, width: w - 4, height: 8
102
+ end
103
+
104
+ title_adjustment = title == "" ? 4 : 14
105
+ at[1] -= title_adjustment
106
+ self.text_box info, size: options[:size], at: at, width: w - 4, height: h - title_adjustment, align: options[:align], style: options[:style], valign: options[:valign]
101
107
  end
102
108
  end
103
109
  end
@@ -1,25 +1,46 @@
1
1
  module BrDanfe
2
2
  class Dup
3
- def self.render(pdf, xml)
4
- pdf.ititle 0.42, 10.00, 0.25, 11.12, "dup.title"
5
- pdf.ibox 0.85, 20.57, 0.25, 11.51
3
+ def initialize(pdf, xml)
4
+ @pdf = pdf
5
+ @xml = xml
6
+ end
7
+
8
+ def render
9
+ @pdf.ititle 0.42, 10.00, 0.25, 11.12, "dup.title"
10
+ @pdf.ibox 0.85, 20.57, 0.25, 11.51
6
11
 
7
12
  x = 0.25
8
13
  y = 11.51
9
- xml.collect("xmlns", "dup") do |det|
10
- normal = { size: 6, border: 0 }
11
- italic = normal.merge({ style: :italic })
12
-
13
- pdf.ibox 0.85, 2.12, x, y, "", I18n.t("danfe.dup.nDup"), italic
14
- pdf.ibox 0.85, 2.12, x + 0.70, y, "", det.css("nDup").text, normal
15
- pdf.ibox 0.85, 2.12, x, y + 0.20, "", I18n.t("danfe.dup.dVenc"), italic
16
- dtduplicata = det.css("dVenc").text
17
- dtduplicata = dtduplicata[8,2] + "/" + dtduplicata[5, 2] + "/" + dtduplicata[0, 4]
18
- pdf.ibox 0.85, 2.12, x + 0.70, y + 0.20, "", dtduplicata, normal
19
- pdf.ibox 0.85, 2.12, x, y + 0.40, "", I18n.t("danfe.dup.vDup"), italic
20
- pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.40, "", det.css("vDup").text, normal
21
- x = x + 2.30
14
+ @xml.collect("xmlns", "dup") do |det|
15
+ render_dup(det, x, y)
16
+ x += 2.30
22
17
  end
23
18
  end
19
+
20
+ private
21
+ def render_dup(det, x, y)
22
+ @pdf.ibox 0.85, 2.12, x, y, "", I18n.t("danfe.dup.nDup"), italic
23
+ @pdf.ibox 0.85, 2.12, x + 0.70, y, "", det.css("nDup").text, normal
24
+ @pdf.ibox 0.85, 2.12, x, y + 0.20, "", I18n.t("danfe.dup.dVenc"), italic
25
+
26
+ @pdf.ibox 0.85, 2.12, x + 0.70, y + 0.20, "", dtduplicata(det), normal
27
+
28
+ @pdf.ibox 0.85, 2.12, x, y + 0.40, "", I18n.t("danfe.dup.vDup"), italic
29
+ @pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.40, "", det.css("vDup").text, normal
30
+ end
31
+
32
+ def dtduplicata(det)
33
+ dtduplicata = det.css("dVenc").text
34
+ dtduplicata = dtduplicata[8,2] + "/" + dtduplicata[5, 2] + "/" + dtduplicata[0, 4]
35
+ dtduplicata
36
+ end
37
+
38
+ def normal
39
+ { size: 6, border: 0 }
40
+ end
41
+
42
+ def italic
43
+ normal.merge({ style: :italic })
44
+ end
24
45
  end
25
46
  end