br_danfe 0.15.1 → 0.17.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +20 -8
  3. data/.github/dependabot.yml +19 -0
  4. data/.rubocop.yml +24 -11
  5. data/.tool-versions +1 -0
  6. data/Gemfile.lock +69 -50
  7. data/Guardfile +4 -2
  8. data/README.md +23 -0
  9. data/bin/_guard-core +29 -0
  10. data/bin/guard +29 -0
  11. data/br_danfe.gemspec +9 -7
  12. data/lib/br_danfe/danfe_lib/nfce.rb +11 -9
  13. data/lib/br_danfe/danfe_lib/nfce_lib/document.rb +1 -1
  14. data/lib/br_danfe/danfe_lib/nfce_lib/footer.rb +2 -2
  15. data/lib/br_danfe/danfe_lib/nfce_lib/header.rb +30 -16
  16. data/lib/br_danfe/danfe_lib/nfce_lib/key.rb +3 -3
  17. data/lib/br_danfe/danfe_lib/nfce_lib/nfce_identification.rb +3 -3
  18. data/lib/br_danfe/danfe_lib/nfce_lib/product_list.rb +44 -53
  19. data/lib/br_danfe/danfe_lib/nfce_lib/recipient.rb +1 -1
  20. data/lib/br_danfe/danfe_lib/nfce_lib/total_list.rb +16 -15
  21. data/lib/br_danfe/danfe_lib/nfe.rb +11 -9
  22. data/lib/br_danfe/danfe_lib/nfe_lib/dest.rb +1 -1
  23. data/lib/br_danfe/danfe_lib/nfe_lib/dup.rb +1 -2
  24. data/lib/br_danfe/danfe_lib/nfe_lib/emit_header.rb +5 -6
  25. data/lib/br_danfe/danfe_lib/nfe_lib/infadic.rb +2 -1
  26. data/lib/br_danfe/document_builder.rb +1 -1
  27. data/lib/br_danfe/helper.rb +8 -10
  28. data/lib/br_danfe/mdfe.rb +55 -0
  29. data/lib/br_danfe/mdfe_lib/authorization_protocol.rb +24 -0
  30. data/lib/br_danfe/mdfe_lib/document.rb +26 -0
  31. data/lib/br_danfe/mdfe_lib/drivers.rb +70 -0
  32. data/lib/br_danfe/mdfe_lib/fisco_control.rb +21 -0
  33. data/lib/br_danfe/mdfe_lib/header.rb +77 -0
  34. data/lib/br_danfe/mdfe_lib/mdfe_identification.rb +69 -0
  35. data/lib/br_danfe/mdfe_lib/notes.rb +94 -0
  36. data/lib/br_danfe/mdfe_lib/totalizer.rb +57 -0
  37. data/lib/br_danfe/mdfe_lib/vehicles.rb +80 -0
  38. data/lib/br_danfe/qr_code.rb +21 -0
  39. data/lib/br_danfe/version.rb +1 -1
  40. data/lib/br_danfe.rb +2 -2
  41. data/spec/br_danfe/danfe_lib/nfce_lib/footer_spec.rb +3 -2
  42. data/spec/br_danfe/danfe_lib/nfce_lib/header_spec.rb +6 -4
  43. data/spec/br_danfe/danfe_lib/nfce_lib/helper_spec.rb +2 -2
  44. data/spec/br_danfe/danfe_lib/nfce_lib/key_spec.rb +2 -2
  45. data/spec/br_danfe/danfe_lib/nfce_lib/nfce_identification_spec.rb +2 -2
  46. data/spec/br_danfe/danfe_lib/nfce_lib/recipient_spec.rb +10 -10
  47. data/spec/br_danfe/danfe_lib/nfce_lib/total_list_spec.rb +12 -12
  48. data/spec/br_danfe/danfe_lib/nfce_spec.rb +2 -1
  49. data/spec/br_danfe/danfe_lib/nfe_lib/cst_spec.rb +4 -4
  50. data/spec/br_danfe/danfe_lib/nfe_lib/dest_spec.rb +178 -178
  51. data/spec/br_danfe/danfe_lib/nfe_lib/det_body_spec.rb +274 -274
  52. data/spec/br_danfe/danfe_lib/nfe_lib/document_spec.rb +77 -77
  53. data/spec/br_danfe/danfe_lib/nfe_lib/dup_spec.rb +23 -23
  54. data/spec/br_danfe/danfe_lib/nfe_lib/emit_header_spec.rb +37 -37
  55. data/spec/br_danfe/danfe_lib/nfe_lib/helper_spec.rb +34 -34
  56. data/spec/br_danfe/danfe_lib/nfe_lib/icmstot_spec.rb +19 -19
  57. data/spec/br_danfe/danfe_lib/nfe_lib/infadic_spec.rb +240 -240
  58. data/spec/br_danfe/danfe_lib/nfe_lib/infadic_vol_spec.rb +3 -2
  59. data/spec/br_danfe/danfe_lib/nfe_lib/issqn_spec.rb +16 -16
  60. data/spec/br_danfe/danfe_lib/nfe_lib/ticket_spec.rb +13 -13
  61. data/spec/br_danfe/danfe_lib/nfe_lib/transp_spec.rb +76 -76
  62. data/spec/br_danfe/danfe_lib/nfe_lib/vol_spec.rb +40 -40
  63. data/spec/br_danfe/danfe_lib/nfe_lib/xprod_spec.rb +118 -118
  64. data/spec/br_danfe/danfe_spec.rb +2 -2
  65. data/spec/br_danfe/helper_spec.rb +26 -14
  66. data/spec/br_danfe/mdfe_lib/authorization_protocol_spec.rb +35 -0
  67. data/spec/br_danfe/mdfe_lib/document_spec.rb +20 -0
  68. data/spec/br_danfe/mdfe_lib/drivers_spec.rb +88 -0
  69. data/spec/br_danfe/mdfe_lib/fisco_control_spec.rb +69 -0
  70. data/spec/br_danfe/mdfe_lib/header_spec.rb +135 -0
  71. data/spec/br_danfe/mdfe_lib/mdfe_identification_spec.rb +104 -0
  72. data/spec/br_danfe/mdfe_lib/notes_spec.rb +97 -0
  73. data/spec/br_danfe/mdfe_lib/totalizer_spec.rb +63 -0
  74. data/spec/br_danfe/mdfe_lib/vehicles_spec.rb +66 -0
  75. data/spec/br_danfe/mdfe_spec.rb +45 -0
  76. data/spec/br_danfe/qr_code_spec.rb +31 -0
  77. data/spec/br_danfe/xml_spec.rb +6 -6
  78. data/spec/fixtures/mdfe/lib/document#render.pdf +0 -0
  79. data/spec/fixtures/mdfe/lib/document#text.align.pdf +0 -0
  80. data/spec/fixtures/mdfe/lib/document#text.pad.pdf +0 -0
  81. data/spec/fixtures/mdfe/lib/document#text.simple.pdf +0 -0
  82. data/spec/fixtures/mdfe/lib/document#text.size.pdf +0 -0
  83. data/spec/fixtures/mdfe/lib/document#text.style.pdf +0 -0
  84. data/spec/fixtures/mdfe/lib/fisco_control#barcode.pdf +0 -0
  85. data/spec/fixtures/mdfe/lib/fisco_control#without-barcode.pdf +0 -0
  86. data/spec/fixtures/mdfe/lib/header#render-qr-code.pdf +0 -0
  87. data/spec/fixtures/mdfe/lib/header#render-with_logo.pdf +0 -0
  88. data/spec/fixtures/mdfe/lib/header#render-without-qr-code.pdf +0 -0
  89. data/spec/fixtures/mdfe/lib/header#render-without_logo.pdf +0 -0
  90. data/spec/fixtures/mdfe/lib/mdfe-with-multiple-pages.pdf +1945 -0
  91. data/spec/fixtures/mdfe/lib/mdfe.fixture.pdf +1286 -0
  92. data/spec/fixtures/mdfe/lib/notes#render-big-aditional-information.pdf +1943 -0
  93. data/spec/fixtures/mdfe/lib/xml-mdfe-multiples-pages.xml +116 -0
  94. data/spec/fixtures/mdfe/lib/xml-mdfe.xml +250 -0
  95. data/spec/fixtures/nfce/lib/document#render.pdf +12 -23
  96. data/spec/fixtures/nfce/lib/footer#render-with_additional_information.pdf +0 -0
  97. data/spec/fixtures/nfce/lib/footer#render.pdf +0 -0
  98. data/spec/fixtures/nfce/lib/header#render-homologation.pdf +0 -0
  99. data/spec/fixtures/nfce/lib/header#render-long_name_with_logo.pdf +0 -0
  100. data/spec/fixtures/nfce/lib/header#render-long_name_without_logo.pdf +0 -0
  101. data/spec/fixtures/nfce/lib/header#render-short_name_with_logo.pdf +0 -0
  102. data/spec/fixtures/nfce/lib/header#render-short_name_without_logo.pdf +0 -0
  103. data/spec/fixtures/nfce/lib/key#render.pdf +0 -0
  104. data/spec/fixtures/nfce/lib/nfce_identification#render.pdf +0 -0
  105. data/spec/fixtures/nfce/lib/product_list#render-with_many_products.pdf +0 -0
  106. data/spec/fixtures/nfce/lib/product_list#render-with_many_products_and_long_names.pdf +0 -0
  107. data/spec/fixtures/nfce/lib/product_list#render-with_single_product.pdf +0 -0
  108. data/spec/fixtures/nfce/lib/product_list#render-with_single_product_and_long_name.pdf +0 -0
  109. data/spec/fixtures/nfce/lib/product_list_with_many_products_and_long_names.xml +2 -2
  110. data/spec/fixtures/nfce/lib/product_list_with_single_product_and_long_name.xml +1 -1
  111. data/spec/fixtures/nfce/lib/recipient#render-company.pdf +0 -0
  112. data/spec/fixtures/nfce/lib/recipient#render-consumer_without_document.pdf +0 -0
  113. data/spec/fixtures/nfce/lib/recipient#render-foreign.pdf +0 -0
  114. data/spec/fixtures/nfce/lib/recipient#render-individual.pdf +0 -0
  115. data/spec/fixtures/nfce/lib/recipient#render-unidentified_consumer.pdf +0 -0
  116. data/spec/fixtures/nfce/lib/total_list#does_not_render-payment_methods.pdf +0 -0
  117. data/spec/fixtures/nfce/lib/total_list#render-grouped_payment_methods.pdf +0 -0
  118. data/spec/fixtures/nfce/lib/total_list#render-totals.pdf +0 -0
  119. data/spec/fixtures/nfce/lib/total_list#render-without_payment.pdf +0 -0
  120. data/spec/fixtures/nfce/lib/total_list#render.pdf +0 -0
  121. data/spec/fixtures/nfce/v4.00/multiples_xmls_on_the_same_pdf.pdf +568 -447
  122. data/spec/fixtures/nfce/v4.00/nfce-unauthorized-hom.fixture.pdf +0 -0
  123. data/spec/fixtures/nfce/v4.00/nfce-unauthorized-prod.fixture.pdf +0 -0
  124. data/spec/fixtures/nfce/v4.00/rendered_nfce.fixture.pdf +0 -0
  125. data/spec/fixtures/nfce/v4.00/saved_nfce.fixture.pdf +0 -0
  126. data/spec/fixtures/qr_code/qr_code#render.pdf +0 -0
  127. data/spec/spec_helper.rb +1 -1
  128. metadata +118 -48
  129. data/lib/br_danfe/danfe_lib/nfce_lib/qr_code.rb +0 -25
  130. data/lib/br_danfe/danfe_lib/nfe_lib/cep.rb +0 -11
  131. data/spec/br_danfe/danfe_lib/nfce_lib/qr_code_spec.rb +0 -35
  132. data/spec/br_danfe/danfe_lib/nfe_lib/cep_spec.rb +0 -10
@@ -10,9 +10,9 @@ module BrDanfe
10
10
  def render
11
11
  @pdf.render_blank_line
12
12
 
13
- @pdf.text 'Consulte pela Chave de Acesso em', size: 7, align: :center, style: :bold
14
- @pdf.text @xml['urlChave'], size: 7, align: :center
15
- @pdf.text @xml['chNFe'].gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, '\\1 '), size: 6, align: :center
13
+ @pdf.text 'Consulte pela Chave de Acesso em', size: 9, align: :center, style: :bold
14
+ @pdf.text @xml['urlChave'], size: 9, align: :center
15
+ @pdf.text @xml['chNFe'].gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, '\\1 '), size: 8, align: :center
16
16
  end
17
17
  end
18
18
  end
@@ -12,9 +12,9 @@ module BrDanfe
12
12
  identification = "NFC-e nº #{@xml['ide/nNF']} Série #{@xml['ide/serie']} #{emitted_at}"
13
13
 
14
14
  @pdf.render_blank_line
15
- @pdf.text identification, size: 7, align: :center, style: :bold
16
- @pdf.text "<b>Protocolo de autorização:</b> #{@xml['infProt/nProt']}", size: 7, align: :center, inline_format: true
17
- @pdf.text "<b>Data de autorização: </b> #{BrDanfe::Helper.format_datetime(@xml['infProt/dhRecbto'])}", size: 7, align: :center, inline_format: true
15
+ @pdf.text identification, size: 9, align: :center, style: :bold
16
+ @pdf.text "<b>Protocolo de autorização:</b> #{@xml['infProt/nProt']}", size: 9, align: :center, inline_format: true
17
+ @pdf.text "<b>Data de autorização: </b> #{BrDanfe::Helper.format_datetime(@xml['infProt/dhRecbto'])}", size: 9, align: :center, inline_format: true
18
18
  end
19
19
  end
20
20
  end
@@ -14,19 +14,54 @@ module BrDanfe
14
14
 
15
15
  private
16
16
 
17
+ def render_headers(headers)
18
+ 2.times { @pdf.render_blank_line }
19
+ cursor = @pdf.cursor
20
+ headers.each_with_index do |header, index|
21
+ cursor -= 10 if index == 1
22
+ @pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: 0.3.cm do
23
+ @pdf.text header[:content], header[:options]
24
+ end
25
+ end
26
+ end
27
+
17
28
  def headers
18
29
  [
19
- header_column('Código', :left),
20
- header_column('Descrição', :left),
21
- header_column('Qtde', :right),
30
+ header_column('CÓDIGO - DESCRIÇÃO', :left),
31
+ header_column('QTD', :left),
22
32
  header_column('UN', :right),
23
- header_column('Vl Unit', :right),
24
- header_column('Vl Total', :right)
33
+ header_column('VL UNIT', :right),
34
+ header_column('TOTAL', :right)
25
35
  ]
26
36
  end
27
37
 
28
38
  def header_column(title, align)
29
- { content: title, options: { align: align, size: 6, style: :bold } }
39
+ { content: title, options: { align: align, size: 9, style: :bold } }
40
+ end
41
+
42
+ def columns
43
+ [
44
+ { width: 6.7.cm, position: 0 },
45
+ { width: 1.7.cm, position: 0.cm },
46
+ { width: 1.cm, position: 1.7.cm },
47
+ { width: 1.7.cm, position: 2.7.cm },
48
+ { width: 2.3.cm, position: 4.4.cm }
49
+ ]
50
+ end
51
+
52
+ def render_products
53
+ @pdf.render_blank_line
54
+ products.each do |product|
55
+ cursor = @pdf.cursor
56
+
57
+ product.each_with_index do |cell, index|
58
+ cursor -= 10 if index == 1
59
+ @pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: 0.3.cm do
60
+ options = cell[:options].merge(overflow: :truncate)
61
+ @pdf.text_box cell[:content], options
62
+ end
63
+ end
64
+ end
30
65
  end
31
66
 
32
67
  def products
@@ -35,9 +70,8 @@ module BrDanfe
35
70
 
36
71
  def product(det)
37
72
  [
38
- cell_text(det.css('prod/cProd').text),
39
- cell_text(det.css('prod/xProd').text),
40
- cell_number(BrDanfe::Helper.numerify(det.css('prod/qCom').text)),
73
+ cell_text("#{det.css('prod/cProd').text} - #{det.css('prod/xProd').text}"),
74
+ cell_text(BrDanfe::Helper.numerify(det.css('prod/qCom').text), align: :left),
41
75
  cell_text(det.css('prod/uCom').text, align: :right),
42
76
  cell_number(BrDanfe::Helper.numerify(det.css('prod/vUnCom').text)),
43
77
  cell_number(BrDanfe::Helper.numerify(det.css('prod/vProd').text))
@@ -45,7 +79,7 @@ module BrDanfe
45
79
  end
46
80
 
47
81
  def cell_text(text, options = {})
48
- cell = { content: text, options: { border_width: 0, size: 6 } }
82
+ cell = { content: text, options: { border_width: 0, size: 9 } }
49
83
  cell[:options].merge!(options)
50
84
  cell
51
85
  end
@@ -53,49 +87,6 @@ module BrDanfe
53
87
  def cell_number(text)
54
88
  cell_text(text, align: :right)
55
89
  end
56
-
57
- def columns
58
- [
59
- { width: 0.9.cm, position: 0 },
60
- { width: 2.6.cm, position: 0.9.cm },
61
- { width: 1.1.cm, position: 3.5.cm },
62
- { width: 0.4.cm, position: 4.6.cm },
63
- { width: 1.2.cm, position: 5.cm },
64
- { width: 1.2.cm, position: 6.2.cm }
65
- ]
66
- end
67
-
68
- def render_headers(headers)
69
- 2.times { @pdf.render_blank_line }
70
- cursor = @pdf.cursor
71
- headers.each_with_index do |header, index|
72
- @pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: 0.2.cm do
73
- @pdf.text header[:content], header[:options]
74
- end
75
- end
76
- end
77
-
78
- def render_products
79
- @pdf.render_blank_line
80
- index_of_product_name = 1
81
- products.each do |product|
82
- box_height = box_height(product[index_of_product_name][:content])
83
- cursor = @pdf.cursor
84
-
85
- product.each_with_index do |cell, index|
86
- @pdf.bounding_box [columns[index][:position], cursor], width: columns[index][:width], height: box_height do
87
- @pdf.text cell[:content], cell[:options]
88
- end
89
- end
90
- end
91
- end
92
-
93
- def box_height(content)
94
- line_height_base = 0.23.cm
95
-
96
- lines = content.scan(/[\s\S]{1,20}( |$)/).length
97
- line_height_base * lines
98
- end
99
90
  end
100
91
  end
101
92
  end
@@ -23,7 +23,7 @@ module BrDanfe
23
23
  private
24
24
 
25
25
  def options
26
- { size: 7, align: :center }
26
+ { size: 9, align: :center }
27
27
  end
28
28
 
29
29
  def identified_recipient?
@@ -18,12 +18,13 @@ module BrDanfe
18
18
  private
19
19
 
20
20
  def subtotal
21
+ @pdf.render_blank_line
21
22
  cursor = @pdf.cursor
22
- @pdf.bounding_box [4.8.cm, cursor], width: 1.4.cm, height: 0.2.cm do
23
- @pdf.text 'Subtotal R$', size: 6, align: :left
23
+ @pdf.bounding_box [3.5.cm, cursor], width: 1.6.cm, height: 0.4.cm do
24
+ @pdf.text 'Subtotal R$', size: 9, align: :left
24
25
  end
25
- @pdf.bounding_box [6.2.cm, cursor], width: 1.2.cm, height: 0.2.cm do
26
- @pdf.text BrDanfe::Helper.numerify(@xml['ICMSTot > vProd'].to_f), size: 6, align: :right
26
+ @pdf.bounding_box [5.1.cm, cursor], width: 1.6.cm, height: 0.4.cm do
27
+ @pdf.text BrDanfe::Helper.numerify(@xml['ICMSTot > vProd'].to_f), size: 9, align: :right
27
28
  end
28
29
  end
29
30
 
@@ -31,16 +32,16 @@ module BrDanfe
31
32
  @pdf.render_blank_line
32
33
 
33
34
  cursor = @pdf.cursor
34
- print_text('Qtde. total de itens', cursor, size: 7, align: :left)
35
- print_text(@xml.css('det').count.to_s, cursor, size: 7, align: :right)
35
+ print_text('QTD. TOTAL DE ITENS', cursor, size: 10, align: :left)
36
+ print_text(@xml.css('det').count.to_s, cursor, size: 10, align: :right)
36
37
 
37
38
  cursor = @pdf.cursor
38
- print_text('Desconto R$', cursor, size: 7, align: :left)
39
- print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vDesc'].to_f), cursor, size: 7, align: :right)
39
+ print_text('DESCONTO R$', cursor, size: 10, align: :left)
40
+ print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vDesc'].to_f), cursor, size: 10, align: :right)
40
41
 
41
42
  cursor = @pdf.cursor
42
- print_text('Valor Total R$', cursor, size: 7, align: :left, style: :bold)
43
- print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vNF'].to_f), cursor, size: 7, align: :right, style: :bold)
43
+ print_text('VALOR TOTAL R$', cursor, size: 10, align: :left, style: :bold)
44
+ print_text(BrDanfe::Helper.numerify(@xml['ICMSTot > vNF'].to_f), cursor, size: 10, align: :right, style: :bold)
44
45
  end
45
46
 
46
47
  def payment_methods
@@ -59,19 +60,19 @@ module BrDanfe
59
60
  @pdf.render_blank_line
60
61
 
61
62
  cursor = @pdf.cursor
62
- print_text('Forma de pagamento', cursor, size: 7, align: :left, style: :bold)
63
- print_text('Valor pago R$', cursor, size: 7, align: :right, style: :bold)
63
+ print_text('FORMA PAGTO.', cursor, size: 9, align: :left, style: :bold)
64
+ print_text('VLR PAGO R$', cursor, size: 9, align: :right, style: :bold)
64
65
 
65
66
  payments.each do |key, value|
66
67
  cursor = @pdf.cursor
67
- print_text(I18n.t("nfce.payment_methods.#{key}"), cursor, size: 7, align: :left)
68
- print_text(BrDanfe::Helper.numerify(value.to_f), cursor, size: 7, align: :right)
68
+ print_text(I18n.t("nfce.payment_methods.#{key}"), cursor, size: 9, align: :left)
69
+ print_text(BrDanfe::Helper.numerify(value.to_f), cursor, size: 9, align: :right)
69
70
  end
70
71
  end
71
72
  end
72
73
 
73
74
  def print_text(text, cursor, options)
74
- @pdf.bounding_box [0, cursor], width: 7.4.cm, height: 0.25.cm do
75
+ @pdf.bounding_box [0, cursor], width: 6.7.cm, height: 0.35.cm do
75
76
  @pdf.text text, options
76
77
  end
77
78
  end
@@ -10,15 +10,17 @@ module BrDanfe
10
10
  def create_watermark
11
11
  @document.create_stamp('has_no_fiscal_value') do
12
12
  @document.fill_color '7d7d7d'
13
- @document.text_box I18n.t('danfe.others.has_no_fiscal_value'),
14
- size: 2.2.cm,
15
- width: @document.bounds.width,
16
- height: @document.bounds.height,
17
- align: :center,
18
- valign: :center,
19
- at: [0, @document.bounds.height],
20
- rotate: 45,
21
- rotate_around: :center
13
+ @document.text_box(
14
+ I18n.t('danfe.others.has_no_fiscal_value'),
15
+ size: 2.2.cm,
16
+ width: @document.bounds.width,
17
+ height: @document.bounds.height,
18
+ align: :center,
19
+ valign: :center,
20
+ at: [0, @document.bounds.height],
21
+ rotate: 45,
22
+ rotate_around: :center
23
+ )
22
24
  end
23
25
  end
24
26
 
@@ -63,7 +63,7 @@ module BrDanfe
63
63
  end
64
64
 
65
65
  def cep
66
- Cep.format(@xml['enderDest/CEP'])
66
+ BrDanfe::Helper.format_cep(@xml['enderDest/CEP'])
67
67
  end
68
68
 
69
69
  def render_line3
@@ -38,8 +38,7 @@ module BrDanfe
38
38
 
39
39
  def dtduplicata(det)
40
40
  dtduplicata = det.css('dVenc').text
41
- dtduplicata = dtduplicata[8, 2] + '/' + dtduplicata[5, 2] + '/' + dtduplicata[0, 4]
42
- dtduplicata
41
+ "#{dtduplicata[8, 2]}/#{dtduplicata[5, 2]}/#{dtduplicata[0, 4]}"
43
42
  end
44
43
 
45
44
  def normal
@@ -38,11 +38,10 @@ module BrDanfe
38
38
  end
39
39
 
40
40
  def address
41
- formatted = @xml['enderEmit/xLgr'] + ', ' + @xml['enderEmit/nro'] + "\n"
42
- formatted += @xml['enderEmit/xBairro'] + ' - ' + cep + "\n"
43
- formatted += @xml['enderEmit/xMun'] + '/' + @xml['enderEmit/UF'] + "\n"
44
- formatted += phone + ' ' + @xml['enderEmit/email']
45
- formatted
41
+ "#{@xml['enderEmit/xLgr']}, #{@xml['enderEmit/nro']}\n" \
42
+ "#{@xml['enderEmit/xBairro']} - #{cep}\n" \
43
+ "#{@xml['enderEmit/xMun']}/#{@xml['enderEmit/UF']}\n" \
44
+ "#{phone} #{@xml['enderEmit/email']}"
46
45
  end
47
46
 
48
47
  def phone
@@ -50,7 +49,7 @@ module BrDanfe
50
49
  end
51
50
 
52
51
  def cep
53
- Cep.format(@xml['enderEmit/CEP'])
52
+ BrDanfe::Helper.format_cep(@xml['enderEmit/CEP'])
54
53
  end
55
54
 
56
55
  def logo
@@ -93,7 +93,8 @@ module BrDanfe
93
93
  end
94
94
 
95
95
  def difal?
96
- @xml['ICMSTot/vICMSUFDest'].to_f != 0
96
+ value = @xml['ICMSTot/vICMSUFDest'].presence || '0.0'
97
+ BigDecimal(value).positive?
97
98
  end
98
99
 
99
100
  def fisco_content
@@ -7,7 +7,7 @@ module BrDanfe
7
7
  bold: "#{BrDanfe.root_path}/fonts/tinos_bold.ttf",
8
8
  italic: "#{BrDanfe.root_path}/fonts/tinos_italic.ttf",
9
9
  bold_italic: "#{BrDanfe.root_path}/fonts/tinos_bold_italic.ttf",
10
- normal: "#{BrDanfe.root_path}/fonts/tinos.ttf",
10
+ normal: "#{BrDanfe.root_path}/fonts/tinos.ttf"
11
11
  }
12
12
 
13
13
  document
@@ -20,18 +20,12 @@ module BrDanfe
20
20
  decimal_part = separated_number[1] || '00'
21
21
  decimal_part += '0' if decimal_part.size < 2
22
22
 
23
- integer_part + ',' + decimal_part
23
+ "#{integer_part},#{decimal_part}"
24
24
  end
25
25
 
26
- def self.format_datetime(xml_datetime)
27
- formated = ''
28
-
29
- unless xml_datetime.empty?
30
- date = DateTime.strptime(xml_datetime, '%Y-%m-%dT%H:%M:%S')
31
- formated = date.strftime('%d/%m/%Y %H:%M:%S')
32
- end
33
-
34
- formated
26
+ def self.format_datetime(xml_datetime, with_time_zone: false)
27
+ formated = with_time_zone ? '%d/%m/%Y %H:%M:%S%:z' : '%d/%m/%Y %H:%M:%S'
28
+ xml_datetime.present? ? Time.parse(xml_datetime).strftime(formated) : ''
35
29
  end
36
30
 
37
31
  def self.nfe?(xml)
@@ -39,5 +33,9 @@ module BrDanfe
39
33
 
40
34
  xml['ide > mod'] == nfe_code
41
35
  end
36
+
37
+ def self.format_cep(cep)
38
+ cep.sub(/(\d{2})(\d{3})(\d{3})/, '\\1.\\2-\\3')
39
+ end
42
40
  end
43
41
  end
@@ -0,0 +1,55 @@
1
+ module BrDanfe
2
+ BLACK_COLOR = '000000'.freeze
3
+ GRAY_COLOR = 'A0A0A0'.freeze
4
+ LIGHT_GRAY_COLOR = 'ECECEC'.freeze
5
+
6
+ class Mdfe
7
+ attr_reader :logo_options
8
+
9
+ def initialize(xml)
10
+ @xml = BrDanfe::XML.new(xml)
11
+ @pdf = MdfeLib::Document.new
12
+ @logo_options = BrDanfe::Logo::Config.new
13
+ end
14
+
15
+ def save_pdf(filename)
16
+ generate
17
+ @pdf.render_file(filename)
18
+ end
19
+
20
+ def render_pdf
21
+ generate
22
+ @pdf.render
23
+ end
24
+
25
+ private
26
+
27
+ def generate
28
+ generate_on_first_page
29
+ generate_on_each_page
30
+ end
31
+
32
+ def generate_on_first_page
33
+ MdfeLib::Totalizer.new(@pdf, @xml).generate
34
+ MdfeLib::AuthorizationProtocol.new(@pdf, @xml).generate
35
+ MdfeLib::FiscoControl.new(@pdf, @xml).generate
36
+ MdfeLib::Vehicles.new(@pdf, @xml).generate
37
+ MdfeLib::Drivers.new(@pdf, @xml).generate
38
+ MdfeLib::Notes.new(@pdf, @xml).generate
39
+ end
40
+
41
+ def generate_on_each_page
42
+ header = MdfeLib::Header.new(@pdf, @xml, @logo_options.logo, @logo_options.logo_dimensions)
43
+ mdfe_identification = MdfeLib::MdfeIdentification.new(@pdf, @xml)
44
+
45
+ @pdf.page_count.times do |i|
46
+ page = i + 1
47
+
48
+ @pdf.go_to_page page
49
+
50
+ header.generate
51
+ mdfe_identification.generate(page)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ module BrDanfe
2
+ module MdfeLib
3
+ class AuthorizationProtocol
4
+ def initialize(pdf, xml)
5
+ @pdf = pdf
6
+ @xml = xml
7
+ end
8
+
9
+ def generate
10
+ authorization
11
+ end
12
+
13
+ private
14
+
15
+ def authorization
16
+ title = 'Protocolo de autorização'
17
+ protocol = "#{@xml['infProt/nProt']} - #{Helper.format_datetime(@xml['infProt/dhRecbto'], with_time_zone: true)}"
18
+
19
+ @pdf.text_box(title, size: 9, align: :left, style: :bold, at: [0, 510])
20
+ @pdf.text_box(protocol, size: 11, align: :left, at: [0, 500])
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ module BrDanfe
2
+ module MdfeLib
3
+ class Document
4
+ def initialize
5
+ @document = BrDanfe::DocumentBuilder.build(
6
+ page_size: 'A4',
7
+ page_layout: :portrait
8
+ )
9
+
10
+ @document.font 'tinos'
11
+ end
12
+
13
+ def method_missing(method_name, *args, &block)
14
+ if @document.respond_to? method_name
15
+ @document.send method_name, *args, &block
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def respond_to_missing?(method_name, include_private = false)
22
+ @document.respond_to?(method_name, include_private) || super
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ module BrDanfe
2
+ module MdfeLib
3
+ class Drivers
4
+ def initialize(pdf, xml)
5
+ @pdf = pdf
6
+ @xml = xml
7
+ end
8
+
9
+ def generate
10
+ @pdf.move_cursor_to 460
11
+ title
12
+ table_titles
13
+ generate_drivers
14
+ end
15
+
16
+ private
17
+
18
+ def title
19
+ title = 'Condutor'
20
+
21
+ @pdf.text_box(title, size: 12, align: :left, style: :bold, at: [250, @pdf.cursor])
22
+ end
23
+
24
+ def table_titles
25
+ cpf = 'CPF'
26
+ name = 'Nome'
27
+
28
+ @pdf.stroke_color GRAY_COLOR
29
+ @pdf.move_down 20
30
+ @pdf.text_box(cpf, size: 9, align: :left, at: [250, @pdf.cursor])
31
+ @pdf.text_box(name, size: 9, align: :left, at: [350, @pdf.cursor])
32
+ @pdf.move_down 10
33
+ @pdf.stroke_horizontal_line(250, 528, at: @pdf.cursor)
34
+ end
35
+
36
+ def generate_drivers
37
+ @pdf.move_cursor_to 425
38
+
39
+ drivers.each_with_index do |driver, index|
40
+ @pdf.bounding_box [250, @pdf.cursor], width: 278, height: 20 do
41
+ @pdf.stroke_color GRAY_COLOR
42
+ @pdf.dash([2], phase: 6)
43
+ @pdf.stroke_horizontal_line(0, 278, at: 26) unless index.zero?
44
+ @pdf.undash
45
+ @pdf.move_down 20
46
+
47
+ driver.each_with_index do |cell, index_driver|
48
+ @pdf.text_box(cell, at: [x_position(index_driver), 20], size: 12)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def drivers
55
+ @xml.collect('xmlns', 'condutor') { |rodo| driver(rodo) }
56
+ end
57
+
58
+ def driver(rodo)
59
+ [
60
+ rodo.css('CPF').text,
61
+ rodo.css('xNome').text
62
+ ]
63
+ end
64
+
65
+ def x_position(index)
66
+ index.even? ? 0 : 100
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,21 @@
1
+ module BrDanfe
2
+ module MdfeLib
3
+ class FiscoControl
4
+ def initialize(pdf, xml)
5
+ @pdf = pdf
6
+ @nfe_key = xml['mdfeProc > protMDFe > infProt > chMDFe']
7
+ end
8
+
9
+ def generate
10
+ @pdf.text_box('CONTROLE DO FISCO', size: 9, align: :left, at: [250, 600])
11
+
12
+ return if @nfe_key.blank?
13
+
14
+ Barby::Code128C.new(@nfe_key).annotate_pdf(@pdf, x: 250, y: 530, height: 50)
15
+
16
+ @pdf.text_box('Chave de Acesso', size: 9, align: :left, style: :bold, at: [250, 510])
17
+ @pdf.text_box(@nfe_key, size: 11, align: :left, at: [250, 500])
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,77 @@
1
+ module BrDanfe
2
+ module MdfeLib
3
+ class Header
4
+ def initialize(pdf, xml, logo, logo_dimensions)
5
+ @pdf = pdf
6
+ @xml = xml
7
+ @logo = logo
8
+ @logo_dimensions = logo_dimensions
9
+ end
10
+
11
+ def generate
12
+ generate_emit
13
+ generate_title
14
+ generate_qr_code if @xml['qrCodMDFe'].present?
15
+ end
16
+
17
+ private
18
+
19
+ def generate_emit
20
+ if @logo.present?
21
+ company(x: 90)
22
+ logo
23
+ else
24
+ company(x: 0)
25
+ end
26
+ end
27
+
28
+ def company(x:)
29
+ @pdf.bounding_box([x, @pdf.cursor], width: 280, height: 80) do
30
+ @pdf.text(@xml['emit/xNome'], size: 12, style: :bold, align: :left)
31
+ @pdf.text(address, align: :left, size: 9)
32
+ @pdf.text(company_informations, size: 9, align: :left, inline_format: true)
33
+ end
34
+ end
35
+
36
+ def address
37
+ "#{@xml['enderEmit/xLgr']}, nº #{@xml['enderEmit/nro']}\n" \
38
+ "#{@xml['enderEmit/xMun']} - #{@xml['enderEmit/UF']} CEP #{cep}\n"
39
+ end
40
+
41
+ def cep
42
+ Helper.format_cep(@xml['enderEmit/CEP'])
43
+ end
44
+
45
+ def company_informations
46
+ "<b>CNPJ: </b>#{@xml['emit/CNPJ']} <b>IE: </b>#{@xml['emit/IE']}"
47
+ end
48
+
49
+ def logo
50
+ bounding_box_size = 80
51
+ logo_options = BrDanfe::Logo::Options.new(bounding_box_size, @logo_dimensions).options
52
+
53
+ @pdf.bounding_box([0, 770], width: bounding_box_size, height: bounding_box_size) do
54
+ @pdf.image @logo, logo_options
55
+ end
56
+ end
57
+
58
+ def generate_title
59
+ title = '<b>DAMDFE</b> - Documento Auxiliar de Manifesto Eletrônico de Documentos Fiscais'
60
+
61
+ @pdf.move_down 15
62
+ @pdf.bounding_box([0, @pdf.cursor], width: 500, height: 20) do
63
+ @pdf.text(title, size: 12, align: :left, inline_format: true)
64
+ end
65
+ end
66
+
67
+ def generate_qr_code
68
+ box_size = 40.mm
69
+ security_margin = box_size + (box_size / 10.0)
70
+
71
+ @pdf.bounding_box([414, 780], width: security_margin, height: security_margin) do
72
+ BrDanfe::QrCode.new(pdf: @pdf, qr_code_tag: @xml['qrCodMDFe'], box_size: box_size).render
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end