br_danfe 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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