├── .gitignore ├── .rspec ├── .ruby-gemset ├── .ruby-version ├── Gemfile ├── README.md ├── Rakefile ├── lib ├── municipios.json ├── ruby_danfe.rb └── ruby_danfe │ ├── cst.rb │ ├── dacte_generator.rb │ ├── dacteos_generator.rb │ ├── danfe_generator.rb │ ├── danfe_nfce_generator.rb │ ├── danfse_generator.rb │ ├── descricao.rb │ ├── document.rb │ ├── helper.rb │ ├── options.rb │ ├── railtie.rb │ ├── ruby_danfe.rb │ ├── version.rb │ └── xml.rb ├── ruby_danfe.gemspec ├── spec ├── features │ └── ruby_danfe_spec.rb ├── fixtures │ ├── 4_decimals_nfe_simples_nacional.xml │ ├── cte.xml │ ├── nfe_date_format_infoadprod_infoadfisco_issues.xml │ ├── nfe_simples_nacional.xml │ ├── nfe_with_fci.xml │ ├── nfe_with_ns.xml │ ├── nfe_without_ns.xml │ └── nfse.xml ├── lib │ ├── cst_spec.rb │ ├── descricao_spec.rb │ ├── helper_spec.rb │ ├── options_spec.rb │ └── ruby_danfe_spec.rb ├── spec_helper.rb └── support │ └── be_same_file_as.rb └── test ├── cteos.xml ├── danfe.xml ├── generate.rb ├── generate_nfce.rb ├── nfce.xml ├── nfe_simples_nacional.xml ├── nfe_with_fci.xml ├── nfe_with_ns.xml └── nfe_without_ns.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_store 3 | *sublime-* 4 | Gemfile.lock 5 | pkg 6 | *.pdf 7 | coverage 8 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color --format documentation --order rand 2 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | ruby-danfe 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-3.2.2 -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | # Specify your gem's dependencies in ruby_danfe.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ruby DANFE 2 | 3 | It generates PDF files for Brazilian DANFE (_Documento Auxiliar da Nota Fiscal Eletrônica_) from a valid NF-e XML. 4 | 5 | It also generates Brazilian DACTE (_Documento Auxiliar do Conhecimento de Transporte Eletrônico_). 6 | 7 | This project is inspired on [NFePHP class](http://www.assembla.com/wiki/show/nfephp/DanfeNFePHP). 8 | 9 | ## Installing 10 | 11 | gem install ruby_danfe 12 | 13 | ## Usage 14 | 15 | If you have the xml saved in a file: 16 | 17 | require "ruby_danfe" 18 | RubyDanfe.generate("sample.pdf", "sample.xml") 19 | RubyDanfe.generate("cte.pdf", "cte.xml", "dacte") 20 | RubyDanfe.generate("cteos.pdf", "cteos.xml", "dacteos") 21 | 22 | If you have the xml in a variable: 23 | 24 | xml = "string xml" 25 | pdf = RubyDanfe.generatePDF(xml) 26 | pdf.render_file "output.pdf" 27 | 28 | You can use some options too! In this example, the product's field quantity will be rendered with 4 decimals after comma: 29 | 30 | xml = "string xml" 31 | RubyDanfe.options = {"quantity_decimals" => 4} 32 | pdf = RubyDanfe.generatePDF(xml) 33 | pdf.render_file "output.pdf" 34 | 35 | If you have some especific option that is global for your project, you can create a file at config/ruby_danfe.yml, then the ruby_danfe always will load this options. Example: 36 | 37 | project_name/config/ruby_danfe.yml 38 | 39 | ruby_danfe: 40 | options: 41 | quantity_decimals: 3 42 | numerify_prod_qcom: false 43 | 44 | 45 | ## Development 46 | 47 | ### Installing dependencies 48 | 49 | You can install all necessaries dependencies using bunder like above: 50 | 51 | $ bundle install 52 | 53 | ### Tests 54 | 55 | #### Manual tests 56 | 57 | At `test` folder you will find the `generate.rb` file. It shows how to generate a pdf file from a valid xml. 58 | 59 | You can use it following the steps above: 60 | 61 | $ cd test 62 | $ ruby generate.rb nfe_with_ns.xml 63 | $ ruby generate.rb cte_with_ns.xml 'dacte' 64 | $ ruby generate.rb cteos_with_ns.xml 'dacteos' 65 | 66 | You can also use an special version of irb with all classes pre-loaded. Just use: 67 | 68 | $ rake console 69 | RubyDanfe.generate("output.pdf", "test/nfe_with_ns.xml") 70 | RubyDanfe.generate("output.pdf", "test/cte.xml", 'dacte') 71 | RubyDanfe.generate("output.pdf", "test/cteos.xml", 'dacteos') 72 | 73 | or 74 | 75 | $ rake console 76 | my_xml_string = "" 77 | file = File.new("test/nfe_with_ns.xml", "r") 78 | while (line = file.gets) 79 | my_xml_string = my_xml_string + line 80 | end 81 | file.close 82 | 83 | xml = RubyDanfe::XML.new(my_xml_string) 84 | pdf = RubyDanfe.generatePDF(xml) 85 | 86 | pdf.render_file "output.pdf" 87 | 88 | #### Automated tests with RSpec 89 | 90 | You can run all specs using: 91 | 92 | $ rspec 93 | 94 | In the `spec/fixtures` folder, you are going to find some xml files. Each one represent a different NF-e context. 95 | 96 | Each xml file must have its respective pdf file. 97 | 98 | If you did some change that caused general visual changes at output pdfs, so you have to rebuild all fixtures pdf files. 99 | 100 | You can do this automagically running the following taks: 101 | 102 | $ rake spec:fixtures:recreate_pdfs 103 | 104 | #### Code coverage 105 | 106 | Code coverage is available through of SimpleCov. Just run `rspec` and open the coverage report in your browser. 107 | 108 | ### Building and publishing 109 | 110 | You can build using one of the above tasks 111 | 112 | $ rake build # Build ruby_danfe-X.X.X.gem into the pkg directory 113 | $ rake install # Build and install ruby_danfe-X.X.X.gem into system gems 114 | $ rake release # Create tag vX.X.X and build and push ruby_danfe-X.X.X.gem to Rubygems 115 | 116 | ## Contributing 117 | 118 | We encourage you to contribute to Ruby DANFE! 119 | 120 | 1. Fork it 121 | 2. Create your feature branch (`git checkout -b my-new-feature`) 122 | 3. Commit your changes (`git commit -am 'Add some feature'`) 123 | 4. Push to the branch (`git push origin my-new-feature`) 124 | 5. Create new Pull Request 125 | 126 | ## License 127 | 128 | Ruby DANFE is released under the [MIT License](http://www.opensource.org/licenses/MIT). 129 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "ruby_danfe" 3 | 4 | desc "Open an irb session preloaded ruby_danfe classes" 5 | task :console do 6 | sh "irb -rubygems -I lib -r ruby_danfe.rb" 7 | end 8 | 9 | namespace :spec do 10 | namespace :fixtures do 11 | desc "Recreate all pdfs fixtures. Use this task always that output pdf format is changed." 12 | task :recreate_pdfs do 13 | Dir["spec/fixtures/nfe*.xml"].each do |f| 14 | puts "Recreating #{f}.fixture.pdf" 15 | RubyDanfe.generate("#{f}.fixture.pdf", "#{f}") 16 | end 17 | 18 | puts "Recreating spec/fixtures/4_decimals_nfe_simples_nacional.xml.fixture.pdf" 19 | RubyDanfe.options = {"quantity_decimals" => 4} 20 | RubyDanfe.generate("spec/fixtures/4_decimals_nfe_simples_nacional.xml.fixture.pdf", "spec/fixtures/4_decimals_nfe_simples_nacional.xml") 21 | 22 | Dir["spec/fixtures/cte*.xml"].each do |f| 23 | puts "Recreating #{f}.fixture.pdf" 24 | RubyDanfe.generate("#{f}.fixture.pdf", "#{f}", :dacte) 25 | end 26 | 27 | Dir["spec/fixtures/nfse*.xml"].each do |f| 28 | puts "Recreating #{f}.fixture.pdf" 29 | RubyDanfe.generate("#{f}.fixture.pdf", "#{f}", :danfse) 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/ruby_danfe.rb: -------------------------------------------------------------------------------- 1 | require_relative 'ruby_danfe/railtie.rb' 2 | -------------------------------------------------------------------------------- /lib/ruby_danfe/cst.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | class Cst 3 | def self.to_danfe(xml) 4 | value = origin(xml) 5 | 6 | if csosn?(xml) 7 | value += xml.css("ICMS/*/CSOSN").text 8 | elsif cst?(xml) 9 | value += xml.css("ICMS/*/CST").text 10 | end 11 | 12 | value 13 | end 14 | 15 | private 16 | def self.origin(xml) 17 | xml.css('ICMS/*/orig').text 18 | end 19 | 20 | def self.cst?(xml) 21 | xml.css("ICMS/*/CST").text != "" 22 | end 23 | 24 | def self.csosn?(xml) 25 | xml.css("ICMS/*/CSOSN").text != "" 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/ruby_danfe/dacte_generator.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | module RubyDanfe 3 | class DacteGenerator 4 | def initialize(xml) 5 | @xml = xml 6 | @pdf = Document.new 7 | end 8 | 9 | def generatePDF 10 | @pdf.repeat :all do 11 | render_emitente 12 | render_tipo_cte 13 | render_tipo_servico 14 | render_tomador 15 | render_forma_de_pagamento 16 | render_infobox 17 | render_remetente 18 | render_destinatario 19 | render_expedidor 20 | render_recebedor 21 | render_tomador_do_servico 22 | render_produto 23 | render_quantidade 24 | render_seguradora 25 | render_valor_da_prestacao 26 | render_impostos 27 | render_documentos_originarios 28 | render_observacoes 29 | render_modal 30 | end 31 | 32 | @pdf 33 | end 34 | 35 | private 36 | def render_emitente 37 | @pdf.ibox 2.27, 7.67, 0.25, 0.54 38 | @pdf.ibox 2.27, 7.67, 0.25, 0.74, '', 39 | @xml['emit/xNome'], 40 | { :align => :center, :size => 9, :border => 0, :style => :bold } 41 | 42 | fone = @xml['enderEmit/fone'] 43 | unless fone.eql?('') 44 | if fone.size > 8 45 | fone = '(' + @xml['enderEmit/fone'][0,2] + ') ' + @xml['enderEmit/fone'][2,5] + '-' + @xml['enderEmit/fone'][6,4] 46 | else 47 | fone = @xml['enderEmit/fone'][0,4] + '-' + @xml['enderEmit/fone'][4,4] 48 | end 49 | end 50 | @pdf.ibox 2.27, 7.67, 0.25, 1.20, '', 51 | @xml['enderEmit/xLgr'] + ", " + @xml['enderEmit/nro'] + "\n" + 52 | @xml['enderEmit/xMun'] + " - " + @xml['enderEmit/UF'] + " " + @xml['enderEmit/xPais'] + "\n" + 53 | "Fone/Fax: " + fone, 54 | { :align => :center, :size => 8, :border => 0, :style => :bold } 55 | 56 | @pdf.ibox 2.27, 7.67, 0.25, 2.30, '', 57 | "CNPJ: " + Helper.format_cnpj(@xml['emit/CNPJ']) + " " + "IE: " + @xml['emit/IE'], 58 | { :align => :center, :size => 7, :border => 0, :style => :bold } 59 | end 60 | 61 | def render_tipo_cte 62 | # tipo ct-e 63 | tpCTe = case @xml['ide/tpCTe'] 64 | when '0' then 'Normal' 65 | when '1' then 'Complemento de Valores' 66 | when '2' then 'Anulação de Valores' 67 | when '3' then 'Substituto' 68 | else '' 69 | end 70 | @pdf.ibox 0.90, 3.84, 0.25, 2.81, 'TIPO DE CT-E', tpCTe, { :align => :center, :size => 8, :style => :bold } 71 | end 72 | 73 | def render_tipo_servico 74 | # tipo servico 75 | tpServ = case @xml['ide/tpServ'] 76 | when '0' then 'Normal' 77 | when '1' then 'Subcontratação' 78 | when '2' then 'Redespacho' 79 | when '3' then 'Redespacho Intermediário' 80 | else '' 81 | end 82 | @pdf.ibox 0.90, 3.83, 4.08, 2.81, 'TIPO DE SERVIÇO', tpServ, { :align => :center, :size => 8, :style => :bold } 83 | end 84 | 85 | def render_tomador 86 | # tomador 87 | if @xml['ide/toma3'] != '' || @xml['ide/toma03'] != '' then 88 | @xml['ide/toma3'] != '' ? tomador = 'toma3' : tomador = 'toma03' 89 | else if @xml['ide/toma4'] != '' || @xml['ide/toma04'] != '' then 90 | @xml['ide/toma4'] != '' ? tomador = 'toma4' : tomador = 'toma04' 91 | end 92 | end 93 | toma = case @xml[tomador + '/toma'] 94 | when '0' then 'Remetente' 95 | when '1' then 'Expedidor' 96 | when '2' then 'Recebedor' 97 | when '3' then 'Destinatário' 98 | when '4' then 'Outros' 99 | else '' 100 | end 101 | @pdf.ibox 0.90, 3.83, 0.25, 3.71, 'TOMADOR DO SERVIÇO', toma, { :align => :center, :size => 8, :style => :bold } 102 | end 103 | 104 | def render_forma_de_pagamento 105 | # forma de pagamento 106 | forma = case @xml['ide/forPag'] 107 | when '0' then 'Pago' 108 | when '1' then 'A pagar' 109 | when '2' then 'Outros' 110 | else '' 111 | end 112 | @pdf.ibox 0.90, 3.83, 4.08, 3.71, 'FORMA DE PAGAMENTO', forma, { :align => :center, :size => 8, :style => :bold } 113 | end 114 | 115 | def render_infobox 116 | # infobox 117 | @pdf.ibox 0.90, 9.39, 7.92, 0.54, '', 'DACTE', { :align => :center, :style => :bold, :size => 12} 118 | @pdf.ibox 0.90, 9.39, 7.92, 0.94, '', 'Documento auxiliar do Conhecimento de Transporte Eletrônico', { :align => :center, :border => 0, :size => 7 } 119 | #@pdf.ibox 0.90, 9.39, 7.92, 1.04, '', 'de Transporte Eletrônico', { :align => :center, :border => 0, :size => 6 } 120 | 121 | # tipo 122 | @pdf.ibox 0.90, 3.43, 17.31, 0.54, '', 'MODAL', { :align => :center, :size => 7 } 123 | 124 | # modal 125 | # modal = case @xml['ide/modal'] 126 | # when '1' then 'Rodoviário' 127 | # when '2' then 'Aéreo' 128 | # when '3' then 'Aquaviário' 129 | # when '4' then 'Ferroviário' 130 | # when '5' then 'Dutoviário' 131 | # else '' 132 | # end 133 | @pdf.ibox 0.90, 3.43, 17.31, 0.84, '', 'RODOVIÁRIO', { :align => :center, :size => 8, :border => 0, :style => :bold } 134 | @pdf.ibox 0.91, 1.98, 7.92, 1.44, 'MODELO', @xml['ide/mod'], {:size => 8, :align => :center} 135 | @pdf.ibox 0.91, 0.75, 9.90, 1.44, 'SERIE', @xml['ide/serie'], {:size => 8, :align => :center} 136 | @pdf.ibox 0.91, 2.48, 10.65, 1.44, 'NÚMERO', @xml['ide/nCT'], {:size => 8, :align => :center} 137 | @pdf.ibox 0.91, 0.97, 13.13, 1.44, 'FL', '1/1', {:size => 8, :align => :center} 138 | emiss = @xml['ide/dhEmi'][8, 2] + '/' + @xml['ide/dhEmi'][5, 2] + '/' + @xml['ide/dhEmi'][0, 4] + " " + 139 | @xml['ide/dhEmi'][11, 8] 140 | 141 | @pdf.ibox 0.91, 3.21, 14.10, 1.44, 'DATA E HORA DE EMISSÃO', emiss, {:size => 8, :align => :center} 142 | @pdf.ibox 0.91, 3.43, 17.31, 1.44, 'INSC. SUFRAMA DESTINATÁRIO', @xml['dest/ISUF'], {:size => 8, :align => :center} 143 | @pdf.ibox 1.13, 12.82, 7.92, 2.35 144 | @pdf.ibarcode 0.85, 12.82, 9.25, 3.35, @xml.attrib('infCte', 'Id')[3..-1] 145 | @pdf.ibox 0.62, 12.82, 7.92, 3.48, 'Chave de acesso', '' 146 | @pdf.ibox 0.90, 12.82, 7.92, 3.62, '', @xml.attrib('infCte', 'Id')[3..-1].gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, "\\1 "), {:style => :bold, :align => :center, :size => 8, :border => 0} 147 | @pdf.ibox 1.13, 12.82, 7.92, 4.10, '', 'Consulta de autenticidade no portal do CT-e, no site da Sefaz Autorizadora, ou em http://www.cte.fazenda.gov.br/portal', 148 | { :align => :center, :valign => :center, :style => :bold, :size => 8 } 149 | @pdf.ibox 0.71, 12.82, 7.92, 5.23, 'Protocolo de Autorização de Uso' 150 | @pdf.ibox 0.90, 12.82, 7.92, 5.38, '', @xml['infProt/nProt'], { :style => :bold, :align => :left, :border => 0, :size => 8 } 151 | @pdf.ibox 1.33, 7.67, 0.25, 4.61, 'CFOP - NATUREZA DA PRESTAÇÃO', @xml['ide/CFOP'] + ' - ' + @xml['ide/natOp'], { :align => :left, :size => 7, :style => :bold } 152 | # UFIni -xMunIni 153 | @pdf.ibox 0.92, 10.25, 0.25, 5.94, 'INÍCIO DA PRESTAÇÃO', @xml['ide/UFIni'] + ' - ' + @xml['ide/xMunIni'] 154 | # UFFim -cMunFim – xMunFim 155 | @pdf.ibox 0.92, 10.24, 10.50, 5.94, 'TÉRMINO DA PRESTAÇÃO', @xml['ide/UFFim'] + ' - ' + @xml['ide/cMunFim'] + ' - ' + @xml['ide/xMunFim'] 156 | end 157 | 158 | def render_remetente 159 | # remetente 160 | @pdf.ibox 2.76, 10.25, 0.25, 6.86 161 | @pdf.ibox 0.90, 10.00, 0.28, 7.05, '', 'Remetente: ', { :size => 7, :border => 0, :style => :italic } 162 | @pdf.ibox 0.90, 10.00, 1.88, 7.05, '', @xml['rem/xNome'], { :size => 7, :border => 0, :style => :bold } 163 | @pdf.ibox 0.90, 10.00, 0.28, 7.41, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 164 | @pdf.ibox 0.90, 10.00, 1.88, 7.41, '', @xml['enderReme/xLgr'] + ', ' + @xml['enderReme/nro'] + (@xml['enderReme/xCpl'] != '' ? ' - ' + @xml['enderReme/xCpl'] : ''), { :size => 7, :border => 0, :style => :bold } if @xml['enderReme/xLgr'] != '' 165 | @pdf.ibox 0.90, 5.00, 1.88, 7.68, '', @xml['enderReme/xBairro'], { :size => 7, :border => 0, :style => :bold } 166 | @pdf.ibox 0.90, 10.00, 0.28, 8.02, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 167 | @pdf.ibox 0.90, 10.00, 1.88, 8.02, '', @xml['enderReme/xMun'], { :size => 7, :border => 0, :style => :bold } 168 | @pdf.ibox 0.90, 3.00, 6.50, 8.02, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 169 | @pdf.ibox 0.90, 3.00, 7.20, 8.02, '', @xml['enderReme/CEP'][0,2] + '.' + @xml['enderReme/CEP'][3,3] + '-' + @xml['enderReme/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderReme/CEP'] != '' 170 | @pdf.ibox 0.90, 10.00, 0.28, 8.41, '', 'CNPJ/CPF: ', { :size => 7, :border => 0, :style => :italic } 171 | @pdf.ibox 0.90, 10.00, 1.88, 8.41, '', Helper.format_cnpj(@xml['rem/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['rem/CNPJ'] != '' 172 | @pdf.ibox 0.90, 10.00, 1.88, 8.41, '', @xml['rem/CPF'][0,3] + '.' + @xml['rem/CPF'][3,3] + '.' + @xml['rem/CPF'][6,3] + '-' + @xml['rem/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['rem/CPF'] != '' 173 | @pdf.ibox 0.90, 3.50, 6.50, 8.41, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 174 | @pdf.ibox 0.90, 3.50, 7.85, 8.41, '', @xml['rem/IE'], { :size => 7, :border => 0, :style => :bold } 175 | @pdf.ibox 0.90, 6.00, 0.28, 8.82, '', 'UF: ' + ' ' + 'País: ', { :size => 7, :border => 0, :style => :italic } 176 | @pdf.ibox 0.90, 6.00, 1.88, 8.82, '', @xml['enderReme/UF'] + ' ' + @xml['enderReme/xPais'], { :size => 7, :border => 0, :style => :bold } 177 | @pdf.ibox 0.90, 3.00, 6.50, 8.82, '', 'Fone: ', { :size => 7, :border => 0, :style => :italic } 178 | fone = @xml['rem/fone'] 179 | unless fone.eql?('') 180 | if fone.size > 8 181 | @pdf.ibox 0.90, 3.00, 7.20, 8.82, '', '(' + @xml['rem/fone'][0,2] + ')' + @xml['rem/fone'][2,4] + '-' + @xml['rem/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 182 | else 183 | @pdf.ibox 0.90, 3.00, 7.20, 8.82, '', @xml['rem/fone'][0,4] + '-' + @xml['rem/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 184 | end 185 | end 186 | end 187 | 188 | def render_destinatario 189 | # destinatário 190 | @pdf.ibox 2.76, 10.24, 10.50, 6.86 191 | @pdf.ibox 0.90, 10.00, 10.53, 7.05, '', 'Destinatário: ', { :size => 7, :border => 0, :style => :italic } 192 | @pdf.ibox 0.90, 10.00, 12.10, 7.05, '', @xml['dest/xNome'], { :size => 7, :border => 0, :style => :bold } 193 | @pdf.ibox 0.90, 10.00, 10.53, 7.41, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 194 | @pdf.ibox 0.90, 10.00, 12.10, 7.41, '', @xml['enderDest/xLgr'] + ', ' + @xml['enderDest/nro'] + (@xml['enderDest/xCpl'] != '' ? ' - ' + @xml['enderDest/xCpl'] : ''), { :size => 7, :border => 0, :style => :bold } if @xml['enderDest/xLgr'] != '' 195 | @pdf.ibox 0.90, 5.00, 12.10, 7.68, '', @xml['enderDest/xBairro'], { :size => 7, :border => 0, :style => :bold } 196 | @pdf.ibox 0.90, 10.00, 10.53, 8.02, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 197 | @pdf.ibox 0.90, 10.00, 12.10, 8.02, '', @xml['enderDest/xMun'], { :size => 7, :border => 0, :style => :bold } 198 | @pdf.ibox 0.90, 3.00, 16.75, 8.02, '', 'CEP: ' , { :size => 7, :border => 0, :style => :italic } 199 | @pdf.ibox 0.90, 3.00, 17.40, 8.02, '', @xml['enderDest/CEP'][0,2] + '.' + @xml['enderDest/CEP'][3,3] + '-' + @xml['enderDest/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderDest/CEP'] != '' 200 | @pdf.ibox 0.90, 10.00, 10.53, 8.41, '', 'CNPJ/CPF: ', { :size => 7, :border => 0, :style => :italic } 201 | @pdf.ibox 0.90, 10.00, 12.10, 8.41, '', Helper.format_cnpj(@xml['dest/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['dest/CNPJ'] != '' 202 | @pdf.ibox 0.90, 10.00, 12.10, 8.41, '', @xml['dest/CPF'][0,3] + '.' + @xml['dest/CPF'][3,3] + '.' + @xml['dest/CPF'][6,3] + '-' + @xml['dest/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['dest/CPF'] != '' 203 | @pdf.ibox 0.90, 3.50, 16.75, 8.41, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 204 | @pdf.ibox 0.90, 3.50, 18.05, 8.41, '', @xml['dest/IE'], { :size => 7, :border => 0, :style => :bold } 205 | @pdf.ibox 0.90, 6.00, 10.53, 8.82, '', 'UF: ' + ' ' + 'País: ' , { :size => 7, :border => 0, :style => :italic } 206 | @pdf.ibox 0.90, 6.00, 12.10, 8.82, '', @xml['enderDest/UF'] + ' ' + @xml['enderDest/xPais'] , { :size => 7, :border => 0, :style => :bold } 207 | @pdf.ibox 0.90, 3.00, 16.75, 8.82, '', 'Fone: ', { :size => 7, :border => 0, :style => :italic } 208 | fone = @xml['dest/fone'] 209 | unless fone.eql?('') 210 | if fone.size > 8 211 | @pdf.ibox 0.90, 3.00, 17.40, 8.82, '', '(' + @xml['dest/fone'][0,2] + ')' + @xml['dest/fone'][2,4] + '-' + @xml['dest/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 212 | else 213 | @pdf.ibox 0.90, 3.00, 17.40, 8.82, '', @xml['dest/fone'][0,4] + '-' + @xml['dest/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 214 | end 215 | end 216 | end 217 | 218 | def render_expedidor 219 | # expedidor 220 | @pdf.ibox 2.76, 10.25, 0.25, 9.62 221 | @pdf.ibox 0.90, 10.00, 0.28, 9.81, '', 'Expedidor: ', { :size => 7, :border => 0, :style => :italic } 222 | @pdf.ibox 0.90, 10.00, 1.88, 9.81, '', @xml['exped/xNome'], { :size => 7, :border => 0, :style => :bold } 223 | @pdf.ibox 0.90, 10.00, 0.28, 10.17, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 224 | @pdf.ibox 0.90, 10.00, 1.88, 10.17, '', @xml['enderExped/xLgr'] + ', ' + @xml['enderExped/nro'] + (@xml['enderExped/xCpl'] != '' ? ' - ' + @xml['enderExped/xCpl'] : ''), { :size => 7, :border => 0, :style => :bold } if @xml['enderExped/xLgr'] != '' 225 | @pdf.ibox 0.90, 5.00, 1.88, 10.44, '', @xml['enderExped/xBairro'], { :size => 7, :border => 0, :style => :bold } 226 | @pdf.ibox 0.90, 10.00, 0.28, 10.78, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 227 | @pdf.ibox 0.90, 10.00, 1.88, 10.78, '', @xml['enderExped/xMun'], { :size => 7, :border => 0, :style => :bold } 228 | @pdf.ibox 0.90, 3.00, 6.50, 10.78, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 229 | @pdf.ibox 0.90, 3.00, 7.20, 10.78, '', @xml['enderExped/CEP'][0,2] + '.' + @xml['enderExped/CEP'][3,3] + '-' + @xml['enderExped/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderExped/CEP'] != '' 230 | @pdf.ibox 0.90, 10.00, 0.28, 11.17, '', 'CNPJ/CPF: ', { :size => 7, :border => 0, :style => :italic } 231 | @pdf.ibox 0.90, 10.00, 1.88, 11.17, '', Helper.format_cnpj(@xml['exped/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['exped/CNPJ'] != '' 232 | @pdf.ibox 0.90, 10.00, 1.88, 11.17, '', @xml['exped/CPF'][0,3] + '.' + @xml['exped/CPF'][3,3] + '.' + @xml['exped/CPF'][6,3] + '-' + @xml['exped/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['exped/CPF'] != '' 233 | @pdf.ibox 0.90, 3.50, 6.50, 11.17, '', 'Inscr. Est.:' , { :size => 7, :border => 0, :style => :italic } 234 | @pdf.ibox 0.90, 3.50, 7.85, 11.17, '', @xml['exped/IE'], { :size => 7, :border => 0, :style => :bold } 235 | @pdf.ibox 0.90, 6.00, 0.28, 11.58, '', 'UF: ' + ' ' + 'País: ', { :size => 7, :border => 0, :style => :italic } 236 | @pdf.ibox 0.90, 6.00, 1.88, 11.58, '', @xml['enderExped/UF'] + ' ' + @xml['enderExped/xPais'], { :size => 7, :border => 0, :style => :bold } 237 | @pdf.ibox 0.90, 3.00, 6.50, 11.58, '', 'Fone: ', { :size => 7, :border => 0, :style => :italic } 238 | fone = @xml['exped/fone'] 239 | unless fone.eql?('') 240 | if @xml['exped/fone'] != '' and fone.size > 8 241 | @pdf.ibox 0.90, 3.00, 7.20, 11.58, '', '(' + @xml['exped/fone'][0,2] + ')' + @xml['exped/fone'][2,4] + '-' + @xml['exped/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 242 | else 243 | @pdf.ibox 0.90, 3.00, 7.20, 11.58, '', @xml['exped/fone'][0,4] + '-' + @xml['exped/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 244 | end 245 | end 246 | end 247 | 248 | def render_recebedor 249 | # recebedor 250 | @pdf.ibox 2.76, 10.24, 10.50, 9.62 251 | @pdf.ibox 0.90, 10.00, 10.53, 9.81, '', 'Recebedor: ', { :size => 7, :border => 0, :style => :italic } 252 | @pdf.ibox 0.90, 10.00, 12.10, 9.81, '', @xml['receb/xNome'], { :size => 7, :border => 0, :style => :bold } 253 | @pdf.ibox 0.90, 10.00, 10.53, 10.17, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 254 | @pdf.ibox 0.90, 10.00, 12.10, 10.17, '', @xml['enderReceb/xLgr'] + ', ' + @xml['enderReceb/nro'] + (@xml['enderReceb/xCpl'] != '' ? ' - ' + @xml['enderReceb/xCpl'] : ''), { :size => 7, :border => 0, :style => :bold } if @xml['enderReceb/xLgr'] != '' 255 | @pdf.ibox 0.90, 5.00, 12.10, 10.44, '', @xml['enderReceb/xBairro'], { :size => 7, :border => 0, :style => :bold } 256 | @pdf.ibox 0.90, 10.00, 10.53, 10.78, '', 'Município: ' , { :size => 7, :border => 0, :style => :italic } 257 | @pdf.ibox 0.90, 10.00, 12.10, 10.78, '', @xml['enderReceb/xMun'], { :size => 7, :border => 0, :style => :bold } 258 | @pdf.ibox 0.90, 3.00, 16.75, 10.78, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 259 | @pdf.ibox 0.90, 3.00, 17.40, 10.78, '', @xml['enderReceb/CEP'][0,2] + '.' + @xml['enderReceb/CEP'][3,3] + '-' + @xml['enderReceb/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderReceb/CEP'] != '' 260 | @pdf.ibox 0.90, 10.00, 10.53, 11.17, '', 'CNPJ/CPF: ', { :size => 7, :border => 0, :style => :italic } 261 | @pdf.ibox 0.90, 10.00, 12.10, 11.17, '', Helper.format_cnpj(@xml['receb/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['receb/CNPJ'] != '' 262 | @pdf.ibox 0.90, 10.00, 12.10, 11.17, '', @xml['receb/CPF'][0,3] + '.' + @xml['receb/CPF'][3,3] + '.' + @xml['receb/CPF'][6,3] + '-' + @xml['receb/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['receb/CPF'] != '' 263 | @pdf.ibox 0.90, 3.50, 16.75, 11.17, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 264 | @pdf.ibox 0.90, 3.50, 18.05, 11.17, '', @xml['receb/IE'], { :size => 7, :border => 0, :style => :bold } 265 | @pdf.ibox 0.90, 6.00, 10.53, 11.58, '', 'UF: ' + ' ' + 'País: ', { :size => 7, :border => 0, :style => :italic } 266 | @pdf.ibox 0.90, 6.00, 12.10, 11.58, '', @xml['enderReceb/UF'] + ' ' + @xml['enderReceb/xPais'], { :size => 7, :border => 0, :style => :bold } 267 | @pdf.ibox 0.90, 3.00, 16.75, 11.58, '', 'Fone: ', { :size => 7, :border => 0, :style => :italic } 268 | fone = @xml['receb/fone'] 269 | unless fone.eql?('') 270 | if @xml['receb/fone'] != '' and fone.size > 8 271 | @pdf.ibox 0.90, 3.00, 17.40, 11.58, '', '(' + @xml['receb/fone'][0,2] + ')' + @xml['receb/fone'][2,4] + '-' + @xml['receb/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 272 | else 273 | @pdf.ibox 0.90, 3.00, 17.40, 11.58, '', @xml['receb/fone'][0,4] + '-' + @xml['receb/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 274 | end 275 | end 276 | end 277 | 278 | def render_tomador_do_servico 279 | # tomador 280 | @pdf.ibox 1.45, 20.49, 0.25, 12.38 281 | if @xml['ide/toma3'] != '' || @xml['ide/toma03'] != '' then 282 | @xml['ide/toma3'] != '' ? tomador = 'toma3' : tomador = 'toma03' 283 | else if @xml['ide/toma4'] != '' || @xml['ide/toma04'] != '' then 284 | @xml['ide/toma4'] != '' ? tomador = 'toma4' : tomador = 'toma04' 285 | end 286 | end 287 | toma = case @xml[tomador + '/toma'] 288 | when '0' then 'rem' 289 | when '1' then 'exped' 290 | when '2' then 'receb' 291 | when '3' then 'dest' 292 | when '4' then 'Outros' 293 | else '' 294 | end 295 | endereco = case @xml[tomador + '/toma'] 296 | when '0' then 'enderReme' 297 | when '1' then 'enderExped' 298 | when '2' then 'enderReceb' 299 | when '3' then 'enderDest' 300 | when '4' then 'Outros' 301 | else '' 302 | end 303 | if toma == 'Outros' 304 | @pdf.ibox 0.90, 10.00, 0.28, 12.45, '', 'Tomador do Serviço: ', { :size => 7, :border => 0, :style => :italic } 305 | @pdf.ibox 0.90, 10.00, 2.58, 12.45, '', @xml['toma4/xNome'], { :size => 7, :border => 0, :style => :bold } 306 | @pdf.ibox 0.90, 10.00, 10.50, 12.45, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 307 | @pdf.ibox 0.90, 10.00, 11.80, 12.45, '', @xml['enderToma/xMun'], { :size => 7, :border => 0, :style => :bold } 308 | @pdf.ibox 0.90, 4.00, 18.00, 12.45, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 309 | @pdf.ibox 0.90, 4.00, 18.70, 12.45, '', @xml['enderToma/CEP'][0,2] + '.' + @xml['enderToma/CEP'][3,3] + '-' + @xml['enderToma/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderToma/CEP'] != '' 310 | @pdf.ibox 0.90, 10.00, 0.28, 12.81, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 311 | @pdf.ibox 0.90, 10.00, 1.88, 12.81, '', @xml['enderToma/xLgr'] + ', ' + @xml['enderToma/nro'] + (@xml['enderToma/xCpl'] != '' ? ' - ' + @xml['enderToma/xCpl'] : '') + ' - ' + @xml['enderToma/xBairro'], { :size => 7, :border => 0, :style => :bold } if @xml['enderToma/xLgr'] != '' 312 | @pdf.ibox 0.90, 2.00, 13.50, 12.81, '', 'UF: ' , { :size => 7, :border => 0, :style => :italic } 313 | @pdf.ibox 0.90, 2.00, 14.50, 12.81, '', @xml['enderToma/UF'], { :size => 7, :border => 0, :style => :bold } 314 | @pdf.ibox 0.90, 5.00, 16.50, 12.81, '', 'País: ' , { :size => 7, :border => 0, :style => :italic } 315 | @pdf.ibox 0.90, 5.00, 17.50, 12.81, '', @xml['enderToma/xPais'], { :size => 7, :border => 0, :style => :bold } 316 | @pdf.ibox 0.90, 5.00, 0.28, 13.17, '', 'CNPJ/CPF: ' , { :size => 7, :border => 0, :style => :italic } 317 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', Helper.format_cnpj(@xml['toma4/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['toma4/CNPJ'] != '' 318 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', @xml['toma4/CPF'][0,3] + '.' + @xml['toma4/CPF'][3,3] + '.' + @xml['toma4/CPF'][6,3] + '-' + @xml['toma4/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['toma4/CPF'] != '' 319 | @pdf.ibox 0.90, 5.00, 5.60, 13.17, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 320 | @pdf.ibox 0.90, 5.00, 7.20, 13.17, '', @xml['toma4/IE'], { :size => 7, :border => 0, :style => :bold } 321 | @pdf.ibox 0.90, 5.00, 10.50, 13.17, '', 'Fone: ' , { :size => 7, :border => 0, :style => :italic } 322 | fone = @xml['toma4/fone'] 323 | unless fone.eql?('') 324 | if fone.size > 8 325 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', '(' + @xml['toma4/fone'][0,2] + ')' + @xml['toma4/fone'][2,4] + '-' + @xml['toma4/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 326 | else 327 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', @xml['toma4/fone'][0,4] + '-' + @xml['toma4/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 328 | end 329 | end 330 | else 331 | @pdf.ibox 0.90, 10.00, 0.28, 12.45, '', 'Tomador do Serviço: ', { :size => 7, :border => 0, :style => :italic } 332 | @pdf.ibox 0.90, 10.00, 2.58, 12.45, '', @xml[toma + '/xNome'], { :size => 7, :border => 0, :style => :bold } 333 | @pdf.ibox 0.90, 10.00, 10.50, 12.45, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 334 | @pdf.ibox 0.90, 10.00, 11.80, 12.45, '', @xml[endereco + '/xMun'], { :size => 7, :border => 0, :style => :bold } 335 | @pdf.ibox 0.90, 4.00, 18.00, 12.45, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 336 | @pdf.ibox 0.90, 4.00, 18.70, 12.45, '', @xml[endereco + '/CEP'][0,2] + '.' + @xml[endereco + '/CEP'][3,3] + '-' + @xml[endereco + '/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml[endereco + '/CEP'] != '' 337 | @pdf.ibox 0.90, 10.00, 0.28, 12.81, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 338 | @pdf.ibox 0.90, 10.00, 1.88, 12.81, '', @xml[endereco + '/xLgr'] + ', ' + @xml[endereco + '/nro'] + (@xml[endereco + '/xCpl'] != '' ? ' - ' + @xml[endereco + '/xCpl'] : '') + ' - ' + @xml[endereco + '/xBairro'], { :size => 7, :border => 0, :style => :bold } if @xml[endereco + '/xLgr'] != '' 339 | @pdf.ibox 0.90, 2.00, 13.50, 12.81, '', 'UF: ' , { :size => 7, :border => 0, :style => :italic } 340 | @pdf.ibox 0.90, 2.00, 14.50, 12.81, '', @xml[endereco + '/UF'], { :size => 7, :border => 0, :style => :bold } 341 | @pdf.ibox 0.90, 5.00, 16.50, 12.81, '', 'País: ' , { :size => 7, :border => 0, :style => :italic } 342 | @pdf.ibox 0.90, 5.00, 17.50, 12.81, '', @xml[endereco + '/xPais'], { :size => 7, :border => 0, :style => :bold } 343 | @pdf.ibox 0.90, 5.00, 0.28, 13.17, '', 'CNPJ/CPF: ' , { :size => 7, :border => 0, :style => :italic } 344 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', Helper.format_cnpj(@xml[toma + '/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml[toma + '/CNPJ'] != '' 345 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', @xml[toma + '/CPF'][0,3] + '.' + @xml[toma + '/CPF'][3,3] + '.' + @xml[toma + '/CPF'][6,3] + '-' + @xml[toma + '/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml[toma + '/CPF'] != '' 346 | @pdf.ibox 0.90, 5.00, 5.60, 13.17, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 347 | @pdf.ibox 0.90, 5.00, 7.20, 13.17, '', @xml[toma + '/IE'], { :size => 7, :border => 0, :style => :bold } 348 | @pdf.ibox 0.90, 5.00, 10.50, 13.17, '', 'Fone: ' , { :size => 7, :border => 0, :style => :italic } 349 | fone = @xml[toma + '/fone'] 350 | unless fone.eql?('') 351 | if fone.size > 8 352 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', '(' + @xml[toma + '/fone'][0,2] + ')' + @xml[toma + '/fone'][2,4] + '-' + @xml[toma + '/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 353 | else 354 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', @xml[toma + '/fone'][0,4] + '-' + @xml[toma + '/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 355 | end 356 | end 357 | end 358 | end 359 | 360 | def render_produto 361 | #produto predominante/outras caract, valor total 362 | #@pdf.ibox 0.92, 20.49, 0.25, 13.82 363 | @pdf.ibox 0.90, 6.83, 0.25, 13.82, 'PRODUTO PREDOMINANTE', @xml['infCarga/proPred'], {:size => 7, :style => :bold } 364 | @pdf.ibox 0.90, 6.83, 7.09, 13.82, 'OUTRAS CARACTERÍSTICAS DA CARGA', @xml['infCarga/xOutCat'], {:size => 7, :style => :bold } 365 | @pdf.ibox 0.90, 6.82, 13.92, 13.82, 'VALOR TOTAL DA MERCADORIA', @xml['infCarga/vCarga'].empty? ? '0,00' : @xml['infCarga/vCarga'], {:size => 7, :style => :bold } 366 | end 367 | 368 | def render_quantidade 369 | #quantidade carga 370 | @pdf.ibox 0.90, 1.07, 0.25, 14.72, '', 'QTD.', { :size => 7, :align => :center, :style => :italic} 371 | @pdf.ibox 0.90, 1.07, 0.25, 15.02, '', 'CARGA', { :size => 7, :align => :center, :style => :italic, :border => 0} 372 | @pdf.ibox 0.90, 3.50, 1.33, 14.72, 'QT./UN. MEDIDA', '', { :size => 7, :style => :italic } 373 | @pdf.ibox 0.90, 3.50, 4.83, 14.72, 'QT./UN. MEDIDA', '', { :size => 7, :style => :italic } 374 | @pdf.ibox 0.90, 3.50, 8.33, 14.72, 'QT./UN. MEDIDA', '', { :size => 7, :style => :italic } 375 | x = 1.33 376 | @xml.collect('xmlns', 'infQ') { |det| 377 | if !det.css('cUnid').text.eql?('00') 378 | desc = "#{det.css('qCarga').text} #{det.css('tpMed').text}" 379 | @pdf.ibox 0.90, 3.50, x, 15.02, '', desc, { :size => 7, :style => :bold, :border => 0 } 380 | x = x + 3.50 381 | end 382 | } 383 | end 384 | 385 | def render_seguradora 386 | #seguradora 387 | respons = case @xml['seg/respSeg'] 388 | when '0' then 'Remetente' 389 | when '1' then 'Expedidor' 390 | when '2' then 'Recebedor' 391 | when '3' then 'Destinatário' 392 | when '4' then 'Emitente do CT-e' 393 | when '5' then 'Tomador de Serviço' 394 | else '' 395 | end 396 | @pdf.ibox 0.30, 8.91, 11.83, 14.72, 'Nome da Seguradora: ' + @xml['seg/xSeg'], '', {:size => 7} 397 | @pdf.ibox 0.60, 3.70, 11.83, 15.02, '', 'Responsável: ' + respons, {:size => 6} 398 | @pdf.ibox 0.60, 2.50, 15.52, 15.02, '', 'Nº Apólice: ' + @xml['seg/nApol'], { :size => 6} 399 | @pdf.ibox 0.60, 2.73, 18.01, 15.02, '', 'Nº Averbação: ' + @xml['seg/nAver'], { :size => 6} 400 | end 401 | 402 | def render_valor_da_prestacao 403 | #componentes do valor da prestação de serviço 404 | @pdf.ibox 0.40, 20.49, 0.25, 15.63, '', 'COMPONENTES DO VALOR DA PRESTAÇÃO DE SERVIÇO', { :align => :left, :size => 7, :style => :bold, :border => 0} 405 | @pdf.ibox 1.40, 4.00, 0.25, 16.03 406 | @pdf.ibox 1.40, 2.12, 0.25, 16.02, 'NOME', '', { :size => 7, :border => 0 } 407 | @pdf.ibox 1.40, 1.88, 3.05, 16.02, 'VALOR', '', { :size => 7, :border => 0 } 408 | @pdf.ibox 1.40, 4.00, 4.26, 16.03 409 | @pdf.ibox 1.40, 2.12, 4.26, 16.02, 'NOME', '', { :size => 7, :border => 0 } 410 | @pdf.ibox 1.40, 1.88, 7.14, 16.02, 'VALOR', '', { :size => 7, :border => 0 } 411 | @pdf.ibox 1.40, 4.00, 8.25, 16.03 412 | @pdf.ibox 1.40, 2.12, 8.25, 16.02, 'NOME', '', { :size => 7, :border => 0 } 413 | @pdf.ibox 1.40, 1.88, 11.05, 16.02, 'VALOR', '', { :size => 7, :border => 0 } 414 | @pdf.ibox 1.40, 4.00, 12.26, 16.03 415 | @pdf.ibox 1.40, 2.12, 12.26, 16.02, 'NOME', '', { :size => 7, :border => 0 } 416 | @pdf.ibox 1.40, 1.88, 15.05, 16.02, 'VALOR', '',{ :size => 7, :border => 0 } 417 | x = 0.25 418 | y = 16.40 419 | @xml.collect('xmlns', 'Comp') { |det| 420 | @pdf.ibox 1.40, 2.12, x, y, '', det.css('xNome').text, { :size => 6, :border => 0, :style => :bold } 421 | @pdf.inumeric 1.40, 1.88, x + 1.80, y, '', det.css('vComp').text, { :size => 7, :border => 0, :align => :right, :style => :bold } 422 | y = y + 0.40 423 | if y > 16.80 424 | x = x + 4.00 425 | y = 16.40 426 | end 427 | } 428 | @pdf.ibox 0.70, 4.48, 16.26, 16.03 429 | @pdf.inumeric 0.70, 4.48, 16.26, 16.03, 'VALOR TOTAL DO SERVIÇO', @xml['vPrest/vTPrest'], { :align => :center, :size => 6, :style => :bold} 430 | @pdf.inumeric 0.70, 4.48, 16.26, 16.73, 'VALOR A RECEBER', @xml['vPrest/vRec'],{ :align => :center, :size => 6, :style => :bold } 431 | end 432 | 433 | def render_impostos 434 | #informações relativas ao Imposto 435 | @pdf.ibox 0.40, 20.49, 0.25, 17.42, '', 'INFORMAÇÕES RELATIVAS AO IMPOSTO', { :align => :left, :size => 7, :border => 0, :style => :bold } 436 | complemento = '' 437 | if !@xml['imp/ICMS/ICMS00'].eql?("") 438 | cst = '00 - Tributação Normal ICMS' 439 | tipoIcms = 'ICMS00' 440 | elsif !@xml['imp/ICMS/ICMS20'].eql?("") 441 | cst = '20 - Tributação com BC reduzida do ICMS' 442 | tipoIcms = 'ICMS20' 443 | elsif !@xml['imp/ICMS/ICMS45'].eql?("") 444 | cst = '40 - ICMS Isenção; 41 - ICMS não tributada; 51 - ICMS diferido' 445 | tipoIcms = 'ICMS45' 446 | elsif !@xml['imp/ICMS/ICMS60'].eql?("") 447 | cst = '60 - ICMS cobrado anteriormente por Substituição Tributária' 448 | tipoIcms = 'ICMS60' 449 | complemento = 'STRet' 450 | elsif !@xml['imp/ICMS/ICMS90'].eql?("") 451 | cst = '90 - ICMS outros' 452 | tipoIcms = 'ICMS90' 453 | elsif !@xml['imp/ICMS/ICMSSN'].eql?("") 454 | cst = 'Simples Nacional' 455 | tipoIcms = 'ICMSSN' 456 | else 457 | cst = '90 - ICMS outros' 458 | tipoIcms = 'ICMSOutraUF' 459 | end 460 | @pdf.ibox 0.90, 10.00, 0.25, 17.83, 'SITUAÇÃO TRIBUTÁRIA', cst, { :size => 7, :style => :bold } 461 | @pdf.inumeric 0.90, 3.00, 10.25, 17.83, 'BASE DE CÁLCULO', @xml['imp/ICMS/'+ tipoIcms + '/vBC'+ complemento], { :size => 7, :style => :bold } 462 | @pdf.inumeric 0.90, 1.00, 13.25, 17.83, 'AL. ICMS', @xml['imp/ICMS/' + tipoIcms + '/pICMS'+ complemento], { :size => 7, :style => :bold } 463 | @pdf.inumeric 0.90, 3.00, 14.25, 17.83, 'VALOR ICMS', @xml['imp/ICMS/' + tipoIcms + '/vICMS'],{ :size => 7, :style => :bold } 464 | @pdf.inumeric 0.90, 2.00, 17.25, 17.83, '% RED.BC.CALC.', @xml['imp/ICMS/' + tipoIcms + '/pRedBC'], { :size => 7, :style => :bold } 465 | @pdf.inumeric 0.90, 1.49, 19.25, 17.83, 'ICMS ST.', @xml['imp/ICMS/' + tipoIcms + '/vICMS'+ complemento], { :size => 7, :style => :bold } 466 | end 467 | 468 | def render_documentos_originarios 469 | #documentos originários 470 | @pdf.ibox 0.40, 20.49, 0.25, 18.73, '', 'DOCUMENTOS ORIGINÁRIOS', { :align => :left, :size => 7, :style => :bold, :border => 0 } 471 | @pdf.ibox 5.52, 1.75, 0.25, 19.13, 'TP DOC.', '', { :size => 7} 472 | @pdf.ibox 5.52, 5.50, 2.00, 19.13, 'CNPJ/CPF EMITENTE/CHAVE', '', { :size => 7} 473 | @pdf.ibox 5.52, 1.00, 7.50, 19.13, 'SÉRIE', '', { :size => 7} 474 | @pdf.ibox 5.52, 2.00, 8.50, 19.13, 'Nº DOCUMENTO', '', { :size => 7} 475 | @pdf.ibox 5.52, 1.75, 10.50, 19.13, 'TP DOC.', '', { :size => 7} 476 | @pdf.ibox 5.52, 5.50, 12.25, 19.13, 'CNPJ/CPF EMITENTE/CHAVE', '', { :size => 7} 477 | @pdf.ibox 5.52, 1.00, 17.75, 19.13, 'SÉRIE', '', { :size => 7} 478 | @pdf.ibox 5.52, 2.00, 18.74, 19.13, 'Nº DOCUMENTO', '', { :size => 7} 479 | x = 0.25 480 | y = 19.43 481 | @xml.collect('xmlns', 'infNF') { |det| 482 | x, y = 0.25, y + 0.25 if x == 20.75 483 | @pdf.ibox 5.52, 1.50, x, y, '', det.css('mod').text, { :size => 7, :border => 0, :style => :bold } 484 | x = x + 1.75 485 | @pdf.ibox 5.52, 2.25, x, y, '', Helper.format_cnpj(@xml['rem/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['rem/CNPJ'] != '' 486 | @pdf.ibox 5.52, 5.25, x, y, '', @xml['rem/CPF'][0,3] + '.' + @xml['rem/CPF'][3,3] + '.' +@xml['rem/CPF'][6,3] + '-' + @xml['rem/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['rem/CPF'] != '' 487 | x = x + 5.50 488 | @pdf.ibox 5.52, 0.75, x, y, '', det.css('serie').text, { :size => 7, :border => 0, :style => :bold } 489 | x = x + 1.00 490 | @pdf.ibox 5.52, 1.75, x, y, '', det.css('nDoc').text, { :size => 7, :border => 0, :style => :bold } 491 | x = x + 2.00 492 | } 493 | # NFe 494 | @xml.collect('xmlns', 'infNFe') { |det| 495 | chave = det.css('chave').text 496 | unless chave.empty? 497 | x, y = 0.25, y + 0.25 if x == 20.75 498 | @pdf.ibox 5.52, 1.50, x, y, '', 'NFe', { :size => 7, :border => 0, :style => :bold } 499 | x = x + 1.75 500 | @pdf.ibox 5.52, 5.25, x, y, '', chave, { :size => 6, :border => 0, :style => :bold } 501 | x = x + 5.50 502 | @pdf.ibox 5.52, 0.75, x, y, '', chave[22, 3], { :size => 7, :border => 0, :style => :bold } 503 | x = x + 1.00 504 | @pdf.ibox 5.52, 1.75, x, y, '', chave[25, 9].gsub(/^[0]+/, ''), { :size => 7, :border => 0, :style => :bold } 505 | x = x + 2.00 506 | end 507 | } 508 | end 509 | 510 | def render_observacoes 511 | #OBSERVAÇÕES 512 | @pdf.ibox 0.40, 20.49, 0.25, 24.65, '', 'OBSERVAÇÕES', { :align => :left, :size => 7, :style => :bold, :border => 0 } 513 | @pdf.ibox 1.40, 20.49, 0.25, 25.05, '', (@xml['compl/xObs'] + "\n CTe COMPLEMENTADO " + "Chave: " + @xml['infCteComp/chave'] + " Valor de serviço: " + 514 | Helper.numerify(@xml['vPresComp/vTPrest']).to_s ), { :align => :left, :size => 7 } 515 | end 516 | 517 | def render_modal 518 | #informações do modal 519 | @pdf.ibox 0.40, 20.49, 0.25, 26.45, '', 'INFORMAÇÕES ESPECÍFICAS DO MODAL RODOVIÁRIO - CARGA FRACIONADA', { :align => :left, :size => 7, :style => :bold, :border => 0} 520 | @pdf.ibox 0.90, 3.00, 0.25, 26.85, 'RNTRC DA EMPRESA', @xml['rodo/RNTRC'], { :size => 7, :style => :bold } 521 | @pdf.ibox 0.90, 3.00, 3.25, 26.85, 'CIOT', @xml['rodo/CIOT'], { :size => 7, :style => :bold } 522 | 523 | dtentrega = @xml['rodo/dPrev'][8, 2].to_s + '/' + @xml['rodo/dPrev'][5, 2].to_s + '/' + @xml['rodo/dPrev'][0, 4].to_s 524 | 525 | @pdf.ibox 0.90, 4.00, 6.25, 26.85, 'DATA PREVISTA DE ENTREGA', dtentrega, { :size => 7, :style => :bold } 526 | @pdf.ibox 0.90, 10.49, 10.25, 26.85, '', 'ESTE CONHECIMENTO DE TRANSPORTE ATENDE A LEGISLAÇÃO DE TRANSPORTE RODOVIÁRIO EM VIGOR', { :size => 5, :align => :center } 527 | 528 | #informações do modal 529 | @pdf.ibox 0.40, 15.49, 0.25, 27.75, '', 'USO EXCLUSIVO DO EMISSOR DO CT-e', { :align => :center, :size => 7 } 530 | @pdf.ibox 1.20, 15.49, 0.25, 28.15, '', '', { :align => :center, :size => 6 } 531 | @pdf.ibox 0.40, 5.00, 15.74, 27.75, '', 'RESERVADO AO FISCO', { :align => :center, :size => 7 } 532 | @pdf.ibox 1.20, 5.00, 15.74, 28.15, '', '', { :align => :center, :size => 6 } 533 | end 534 | end 535 | end 536 | -------------------------------------------------------------------------------- /lib/ruby_danfe/dacteos_generator.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | module RubyDanfe 3 | class DacteosGenerator < RubyDanfe::DacteGenerator 4 | 5 | 6 | def render_infobox 7 | # infobox 8 | @pdf.ibox 0.90, 9.39, 7.92, 0.54, '', 'DACTEOS', { :align => :center, :style => :bold, :size => 12} 9 | @pdf.ibox 0.90, 9.39, 7.92, 0.94, '', 'Documento auxiliar do Conhecimento de Transporte Eletrônico para Outros Serviços', { :align => :center, :border => 0, :size => 7 } 10 | 11 | @pdf.ibox 0.90, 3.43, 17.31, 0.54, '', 'MODAL', { :align => :center, :size => 7 } 12 | @pdf.ibox 0.90, 3.43, 17.31, 0.84, '', 'RODOVIÁRIO', { :align => :center, :size => 8, :border => 0, :style => :bold } 13 | @pdf.ibox 0.91, 1.98, 7.92, 1.44, 'MODELO', @xml['ide/mod'], {:size => 8, :align => :center} 14 | @pdf.ibox 0.91, 0.75, 9.90, 1.44, 'SERIE', @xml['ide/serie'], {:size => 8, :align => :center} 15 | @pdf.ibox 0.91, 2.48, 10.65, 1.44, 'NÚMERO', @xml['ide/nCT'], {:size => 8, :align => :center} 16 | @pdf.ibox 0.91, 0.97, 13.13, 1.44, 'FL', '1/1', {:size => 8, :align => :center} 17 | emiss = @xml['ide/dhEmi'][8, 2] + '/' + @xml['ide/dhEmi'][5, 2] + '/' + @xml['ide/dhEmi'][0, 4] + " " + 18 | @xml['ide/dhEmi'][11, 8] 19 | 20 | @pdf.ibox 0.91, 3.21, 14.10, 1.44, 'DATA E HORA DE EMISSÃO', emiss, {:size => 8, :align => :center} 21 | @pdf.ibox 0.91, 3.43, 17.31, 1.44, 'INSC. SUFRAMA DESTINATÁRIO', @xml['dest/ISUF'], {:size => 8, :align => :center} 22 | @pdf.ibox 1.13, 12.82, 7.92, 2.35 23 | @pdf.ibarcode 0.85, 12.82, 9.25, 3.35, @xml.attrib('infCte', 'Id')[3..-1] 24 | @pdf.ibox 0.62, 12.82, 7.92, 3.48, 'Chave de acesso', '' 25 | @pdf.ibox 0.90, 12.82, 7.92, 3.62, '', @xml.attrib('infCte', 'Id')[3..-1].gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, "\\1 "), {:style => :bold, :align => :center, :size => 8, :border => 0} 26 | @pdf.ibox 1.13, 12.82, 7.92, 4.10, '', 'Consulta de autenticidade no portal do CT-e, no site da Sefaz Autorizadora, ou em http://www.cte.fazenda.gov.br/portal', 27 | { :align => :center, :valign => :center, :style => :bold, :size => 8 } 28 | @pdf.ibox 0.71, 12.82, 7.92, 5.23, 'Protocolo de Autorização de Uso' 29 | @pdf.ibox 0.90, 12.82, 7.92, 5.38, '', @xml['infProt/nProt'], { :style => :bold, :align => :left, :border => 0, :size => 8 } 30 | @pdf.ibox 1.33, 7.67, 0.25, 4.61, 'CFOP - NATUREZA DA PRESTAÇÃO', @xml['ide/CFOP'] + ' - ' + @xml['ide/natOp'], { :align => :left, :size => 7, :style => :bold } 31 | # UFIni -xMunIni 32 | @pdf.ibox 0.92, 10.25, 0.25, 5.94, 'INÍCIO DA PRESTAÇÃO', @xml['ide/UFIni'] + ' - ' + @xml['ide/xMunIni'] 33 | # UFFim -cMunFim – xMunFim 34 | @pdf.ibox 0.92, 10.24, 10.50, 5.94, 'TÉRMINO DA PRESTAÇÃO', @xml['ide/UFFim'] + ' - ' + @xml['ide/cMunFim'] + ' - ' + @xml['ide/xMunFim'] 35 | end 36 | 37 | def render_tomador 38 | # tomador 39 | toma_cnpj = @xml['toma/CNPJ'] 40 | @pdf.ibox 0.90, 3.83, 0.25, 3.71, 'TOMADOR DO SERVIÇO', Helper.format_cnpj(toma_cnpj), { :align => :center, :size => 8, :style => :bold } 41 | end 42 | 43 | 44 | def render_tomador_do_servico 45 | # tomador 46 | @pdf.ibox 1.45, 20.49, 0.25, 12.38 47 | 48 | endereco = 'enderToma' 49 | @pdf.ibox 0.90, 10.00, 0.28, 12.45, '', 'Tomador do Serviço: ', { :size => 7, :border => 0, :style => :italic } 50 | @pdf.ibox 0.90, 10.00, 2.58, 12.45, '', @xml['toma/xNome'], { :size => 7, :border => 0, :style => :bold } 51 | @pdf.ibox 0.90, 10.00, 10.50, 12.45, '', 'Município: ', { :size => 7, :border => 0, :style => :italic } 52 | @pdf.ibox 0.90, 10.00, 11.80, 12.45, '', @xml['enderToma/xMun'], { :size => 7, :border => 0, :style => :bold } 53 | @pdf.ibox 0.90, 4.00, 18.00, 12.45, '', 'CEP: ', { :size => 7, :border => 0, :style => :italic } 54 | @pdf.ibox 0.90, 4.00, 18.70, 12.45, '', @xml['enderToma/CEP'][0,2] + '.' + @xml['enderToma/CEP'][3,3] + '-' + @xml['enderToma/CEP'][5,3], { :size => 7, :border => 0, :style => :bold } if @xml['enderToma/CEP'] != '' 55 | @pdf.ibox 0.90, 10.00, 0.28, 12.81, '', 'Endereço: ', { :size => 7, :border => 0, :style => :italic } 56 | @pdf.ibox 0.90, 10.00, 1.88, 12.81, '', @xml['enderToma/xLgr'] + ', ' + @xml['enderToma/nro'] + (@xml['enderToma/xCpl'] != '' ? ' - ' + @xml['enderToma/xCpl'] : '') + ' - ' + @xml['enderToma/xBairro'], { :size => 7, :border => 0, :style => :bold } if @xml['enderToma/xLgr'] != '' 57 | @pdf.ibox 0.90, 2.00, 13.50, 12.81, '', 'UF: ' , { :size => 7, :border => 0, :style => :italic } 58 | @pdf.ibox 0.90, 2.00, 14.50, 12.81, '', @xml['enderToma/UF'], { :size => 7, :border => 0, :style => :bold } 59 | @pdf.ibox 0.90, 5.00, 16.50, 12.81, '', 'País: ' , { :size => 7, :border => 0, :style => :italic } 60 | @pdf.ibox 0.90, 5.00, 17.50, 12.81, '', @xml['enderToma/xPais'], { :size => 7, :border => 0, :style => :bold } 61 | @pdf.ibox 0.90, 5.00, 0.28, 13.17, '', 'CNPJ/CPF: ' , { :size => 7, :border => 0, :style => :italic } 62 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', Helper.format_cnpj(@xml['toma/CNPJ']), { :size => 7, :border => 0, :style => :bold } if @xml['toma/CNPJ'] != '' 63 | @pdf.ibox 0.90, 5.00, 1.88, 13.17, '', @xml['toma/CPF'][0,3] + '.' + @xml['toma/CPF'][3,3] + '.' + @xml['toma/CPF'][6,3] + '-' + @xml['toma/CPF'][9,2], { :size => 7, :border => 0, :style => :bold } if @xml['toma/CPF'] != '' 64 | @pdf.ibox 0.90, 5.00, 5.60, 13.17, '', 'Inscr. Est.: ', { :size => 7, :border => 0, :style => :italic } 65 | @pdf.ibox 0.90, 5.00, 7.20, 13.17, '', @xml['toma/IE'], { :size => 7, :border => 0, :style => :bold } 66 | @pdf.ibox 0.90, 5.00, 10.50, 13.17, '', 'Fone: ' , { :size => 7, :border => 0, :style => :italic } 67 | fone = @xml['toma/fone'] 68 | unless fone.eql?('') 69 | if fone.size > 8 70 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', '(' + @xml['toma/fone'][0,2] + ')' + @xml['toma/fone'][2,4] + '-' + @xml['toma/fone'][6,4], { :size => 7, :border => 0, :style => :bold } 71 | else 72 | @pdf.ibox 0.90, 5.00, 11.80, 13.17, '', @xml['toma/fone'][0,4] + '-' + @xml['toma/fone'][4,4], { :size => 7, :border => 0, :style => :bold } 73 | end 74 | end 75 | end 76 | 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /lib/ruby_danfe/danfe_generator.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | module RubyDanfe 3 | class DanfeGenerator 4 | def initialize(xml) 5 | @xml = xml 6 | @pdf = Document.new 7 | @vol = 0 8 | end 9 | 10 | def generatePDF 11 | @pdf.repeat :all do 12 | render_canhoto 13 | render_emitente 14 | render_dados_adicionais_box 15 | end 16 | 17 | @pdf.repeat :all, dynamic: true do 18 | render_cabecalho_dos_produtos(@pdf.page_number) 19 | end 20 | 21 | render_titulo 22 | render_faturas 23 | render_calculo_do_imposto 24 | render_transportadora_e_volumes 25 | render_calculo_do_issqn 26 | 27 | render_dados_adicionais 28 | 29 | @pdf.go_to_page(1) 30 | render_produtos 31 | 32 | @pdf.page_count.times do |i| 33 | @pdf.go_to_page(i + 1) 34 | @pdf.ibox 1.00, 3.08, 6.71, 5.54, '', 35 | "FOLHA #{i + 1} de #{@pdf.page_count}", {:size => 8, :align => :center, :valign => :center, :border => 0, :style => :bold} 36 | end 37 | 38 | @pdf 39 | end 40 | 41 | private 42 | def render_canhoto 43 | @pdf.ibox 0.85, 16.10, 0.25, 0.42, "RECEBEMOS DE " + @xml['emit/xNome'] + " OS PRODUTOS CONSTANTES DA NOTA FISCAL INDICADA ABAIXO" 44 | @pdf.ibox 0.85, 4.10, 0.25, 1.27, "DATA DE RECEBIMENTO" 45 | @pdf.ibox 0.85, 12.00, 4.35, 1.27, "IDENTIFICAÇÃO E ASSINATURA DO RECEBEDOR" 46 | 47 | @pdf.ibox 1.70, 4.50, 16.35, 0.42, '', 48 | "NF-e\n" + 49 | "N°. " + @xml['ide/nNF'] + "\n" + 50 | "SÉRIE " + @xml['ide/serie'], {:align => :center, :valign => :center} 51 | end 52 | 53 | def render_emitente 54 | @pdf.ibox 3.92, 6.46, 0.25, 2.54, '', 55 | @xml['emit/xNome'] + "\n" + 56 | @xml['enderEmit/xLgr'] + ", " + @xml['enderEmit/nro'] + "\n" + 57 | @xml['enderEmit/xBairro'] + " - " + @xml['enderEmit/CEP'] + "\n" + 58 | @xml['enderEmit/xMun'] + "/" + @xml['enderEmit/UF'] + "\n" + 59 | @xml['enderEmit/fone'] + " " + @xml['enderEmit/email'], {:align => :center, :valign => :center} 60 | 61 | @pdf.ibox 3.92, 3.08, 6.71, 2.54 62 | 63 | @pdf.ibox 0.60, 3.08, 6.71, 2.54, '', "DANFE", {:size => 12, :align => :center, :border => 0, :style => :bold} 64 | @pdf.ibox 1.20, 3.08, 6.71, 3.14, '', "DOCUMENTO AUXILIAR DA NOTA FISCAL ELETRÔNICA", {:size => 8, :align => :center, :border => 0} 65 | @pdf.ibox 0.60, 3.08, 6.71, 4.34, '', "#{@xml['ide/tpNF']} - " + (@xml['ide/tpNF'] == '0' ? 'ENTRADA' : 'SAÍDA'), {:size => 8, :align => :center, :border => 0} 66 | 67 | @pdf.ibox 1.00, 3.08, 6.71, 4.94, '', 68 | "N°. " + @xml['ide/nNF'] + "\n" + 69 | "SÉRIE " + @xml['ide/serie'], {:size => 8, :align => :center, :valign => :center, :border => 0, :style => :bold} 70 | 71 | @pdf.ibox 2.20, 11.02, 9.79, 2.54 72 | @pdf.ibarcode 1.50, 8.00, 10.4010, 4.44, @xml['chNFe'] 73 | @pdf.ibox 0.85, 11.02, 9.79, 4.74, "CHAVE DE ACESSO", @xml['chNFe'].gsub(/\D/, '').gsub(/(\d)(?=(\d\d\d\d)+(?!\d))/, "\\1 "), {:style => :bold, :align => :center} 74 | @pdf.ibox 0.85, 11.02, 9.79, 5.60 , '', "Consulta de autenticidade no portal nacional da NF-e www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizadora", {:align => :center, :size => 8} 75 | @pdf.ibox 0.85, 10.54, 0.25, 6.46, "NATUREZA DA OPERAÇÃO", @xml['ide/natOp'] 76 | @pdf.ibox 0.85, 10.02, 10.79, 6.46, "PROTOCOLO DE AUTORIZAÇÃO DE USO", @xml['infProt/nProt'] + ' ' + Helper.format_datetime(@xml['infProt/dhRecbto']) , {:align => :center} 77 | @pdf.ibox 0.85, 6.86, 0.25, 7.31, "INSCRIÇÃO ESTADUAL", @xml['emit/IE'] 78 | @pdf.ibox 0.85, 6.86, 7.11, 7.31, "INSC.ESTADUAL DO SUBST. TRIBUTÁRIO", @xml['emit/IEST'] 79 | @pdf.ibox 0.85, 6.84, 13.97, 7.31, "CNPJ", @xml['emit/CNPJ'] 80 | end 81 | 82 | def render_titulo 83 | @pdf.ititle 0.42, 10.00, 0.25, 8.16, "DESTINATÁRIO / REMETENTE" 84 | 85 | @pdf.ibox 0.85, 12.32, 0.25, 8.58, "NOME/RAZÃO SOCIAL", @xml['dest/xNome'] 86 | @pdf.ibox 0.85, 5.33, 12.57, 8.58, "CNPJ/CPF", @xml['dest/CNPJ'] if @xml['dest/CNPJ'] != '' 87 | @pdf.ibox 0.85, 5.33, 12.57, 8.58, "CNPJ/CPF", @xml['dest/CPF'] if @xml['dest/CPF'] != '' 88 | @pdf.ibox 0.85, 5.33, 12.57, 8.58, "CNPJ/CPF/Passaporte", @xml['dest/idEstrangeiro'] if @xml['dest/idEstrangeiro'] != '' 89 | @pdf.ibox 0.85, 2.92, 17.90, 8.58, "DATA DA EMISSÃO", (not @xml['ide/dEmi'].empty?) ? Helper.format_date(@xml['ide/dEmi']) : Helper.format_date(@xml['ide/dhEmi']) , {:align => :right} 90 | @pdf.ibox 0.85, 10.16, 0.25, 9.43, "ENDEREÇO", @xml['enderDest/xLgr'] + " " + @xml['enderDest/nro'] 91 | @pdf.ibox 0.85, 4.83, 10.41, 9.43, "BAIRRO", @xml['enderDest/xBairro'] 92 | @pdf.ibox 0.85, 2.67, 15.24, 9.43, "CEP", @xml['enderDest/CEP'] 93 | @pdf.ibox 0.85, 2.92, 17.90, 9.43, "DATA DA SAÍDA/ENTRADA", (not @xml['ide/dSaiEnt'].empty?) ? Helper.format_date(@xml['ide/dSaiEnt']) : Helper.format_date(@xml['ide/dhSaiEnt']), {:align => :right} 94 | @pdf.ibox 0.85, 7.11, 0.25, 10.28, "MUNICÍPIO", @xml['enderDest/xMun'] 95 | @pdf.ibox 0.85, 4.06, 7.36, 10.28, "FONE/FAX", @xml['enderDest/fone'] 96 | @pdf.ibox 0.85, 1.14, 11.42, 10.28, "UF", @xml['enderDest/UF'] 97 | @pdf.ibox 0.85, 5.33, 12.56, 10.28, "INSCRIÇÃO ESTADUAL", @xml['dest/IE'] 98 | @pdf.ibox 0.85, 2.92, 17.90, 10.28, "HORA DE SAÍDA", Helper.format_time(@xml['ide/hSaiEnt']), {:align => :right} 99 | @pdf.ibox 0.85, 2.92, 17.90, 10.28, "HORA DE SAÍDA", (not @xml['ide/hSaiEnt'].empty?) ? Helper.format_time(@xml['ide/hSaiEnt']) : Helper.extract_time_from_date(@xml['ide/dhSaiEnt']) , {:align => :right} 100 | end 101 | 102 | def render_faturas 103 | @pdf.ititle 0.42, 10.00, 0.25, 11.12, "FATURA / DUPLICATAS" 104 | @pdf.ibox 0.85, 20.57, 0.25, 11.51 105 | 106 | x = 0.25 107 | y = 11.51 108 | @xml.collect('xmlns', 'dup') do |det| 109 | @pdf.ibox 0.85, 2.12, x, y, '', 'Núm.:', { :size => 6, :border => 0, :style => :italic } 110 | @pdf.ibox 0.85, 2.12, x + 0.70, y, '', det.css('nDup').text, { :size => 6, :border => 0 } 111 | @pdf.ibox 0.85, 2.12, x, y + 0.20, '', 'Venc.:', { :size => 6, :border => 0, :style => :italic } 112 | dtduplicata = det.css('dVenc').text 113 | dtduplicata = dtduplicata[8,2] + '/' + dtduplicata[5, 2] + '/' + dtduplicata[0, 4] 114 | @pdf.ibox 0.85, 2.12, x + 0.70, y + 0.20, '', dtduplicata, { :size => 6, :border => 0 } 115 | @pdf.ibox 0.85, 2.12, x, y + 0.40, '', 'Valor: R$', { :size => 6, :border => 0, :style => :italic } 116 | @pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.40, '', det.css('vDup').text, { :size => 6, :border => 0 } 117 | x = x + 2.30 118 | end 119 | 120 | @xml.collect('xmlns', 'fat') do |det| 121 | @pdf.ibox 0.85, 2.12, x, y, '', 'Núm.:', { :size => 4, :border => 0, :style => :italic } 122 | @pdf.ibox 0.85, 2.12, x + 0.70, y, '', det.css('nFat').text, { :size => 4, :border => 0 } 123 | 124 | @pdf.ibox 0.85, 2.12, x, y + 0.20, '', 'vOrig.: R$', { :size => 4, :border => 0, :style => :italic } 125 | @pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.18, '', det.css('vOrig').text, { :size => 4, :border => 0 } 126 | 127 | @pdf.ibox 0.85, 2.12, x, y + 0.40, '', 'vDesc: R$', { :size => 4, :border => 0, :style => :italic } 128 | @pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.36, '', det.css('vDesc').text, { :size => 4, :border => 0 } 129 | 130 | @pdf.ibox 0.85, 2.12, x, y + 0.55, '', 'vLiq: R$', { :size => 4, :border => 0, :style => :italic } 131 | @pdf.inumeric 0.85, 1.25, x + 0.70, y + 0.54, '', det.css('vLiq').text, { :size => 4, :border => 0 } 132 | 133 | x = x + 2.30 134 | end 135 | end 136 | 137 | def render_calculo_do_imposto 138 | @pdf.ititle 0.42, 5.60, 0.25, 12.36, "CÁLCULO DO IMPOSTO" 139 | 140 | @pdf.inumeric 0.85, 4.06, 0.25, 12.78, "BASE DE CÁLCULO DO ICMS", @xml['ICMSTot/vBC'] 141 | @pdf.inumeric 0.85, 4.06, 4.31, 12.78, "VALOR DO ICMS", @xml['ICMSTot/vICMS'] 142 | @pdf.inumeric 0.85, 4.06, 8.37, 12.78, "BASE DE CÁLCULO DO ICMS ST", @xml['ICMSTot/vBCST'] 143 | @pdf.inumeric 0.85, 4.06, 12.43, 12.78, "VALOR DO ICMS ST", @xml['ICMSTot/vST'] 144 | @pdf.inumeric 0.85, 4.32, 16.49, 12.78, "VALOR TOTAL DOS PRODUTOS", @xml['ICMSTot/vProd'] 145 | @pdf.inumeric 0.85, 3.46, 0.25, 13.63, "VALOR DO FRETE", @xml['ICMSTot/vFrete'] 146 | @pdf.inumeric 0.85, 3.46, 3.71, 13.63, "VALOR DO SEGURO", @xml['ICMSTot/vSeg'] 147 | @pdf.inumeric 0.85, 3.46, 7.17, 13.63, "DESCONTO", @xml['ICMSTot/vDesc'] 148 | @pdf.inumeric 0.85, 3.46, 10.63, 13.63, "OUTRAS DESPESAS ACESSORIAS", @xml['ICMSTot/vOutro'] 149 | @pdf.inumeric 0.85, 3.46, 14.09, 13.63, "VALOR DO IPI", @xml['ICMSTot/vIPI'] 150 | @pdf.inumeric 0.85, 3.27, 17.55, 13.63, "VALOR TOTAL DA NOTA", @xml['ICMSTot/vNF'], :style => :bold 151 | end 152 | 153 | def render_transportadora_e_volumes 154 | @pdf.ititle 0.42, 10.00, 0.25, 14.48, "TRANSPORTADOR / VOLUMES TRANSPORTADOS" 155 | 156 | @pdf.ibox 0.85, 9.02, 0.25, 14.90, "RAZÃO SOCIAL", @xml['transporta/xNome'] 157 | @pdf.ibox 0.85, 2.79, 9.27, 14.90, "FRETE POR CONTA", descricao_modalidade_frete(@xml['transp/modFrete']) 158 | @pdf.ibox 0.85, 1.78, 12.06, 14.90, "CODIGO ANTT", @xml['veicTransp/RNTC'] 159 | @pdf.ibox 0.85, 2.29, 13.84, 14.90, "PLACA DO VEÍCULO", @xml['veicTransp/placa'] 160 | @pdf.ibox 0.85, 0.76, 16.13, 14.90, "UF", @xml['veicTransp/UF'] 161 | @pdf.ibox 0.85, 3.94, 16.89, 14.90, "CNPJ/CPF", @xml['transporta/CNPJ'] 162 | @pdf.ibox 0.85, 9.02, 0.25, 15.75, "ENDEREÇO", @xml['transporta/xEnder'] 163 | @pdf.ibox 0.85, 6.86, 9.27, 15.75, "MUNICÍPIO", @xml['transporta/xMun'] 164 | @pdf.ibox 0.85, 0.76, 16.13, 15.75, "UF", @xml['transporta/UF'] 165 | @pdf.ibox 0.85, 3.94, 16.89, 15.75, "INSCRIÇÂO ESTADUAL", @xml['transporta/IE'] 166 | 167 | @vol = 0 168 | 169 | quantidade = 0 170 | peso_bruto = 0 171 | peso_liquido = 0 172 | 173 | especie = nil 174 | marca = nil 175 | 176 | @xml.collect('xmlns', 'vol') do |det| 177 | @vol += 1 178 | quantidade += det.css('qVol').text.to_f 179 | peso_bruto += det.css('pesoB').text.to_f 180 | peso_liquido += det.css('pesoL').text.to_f 181 | 182 | especie ||= det.css('esp').text 183 | marca ||= det.css('marca').text 184 | end 185 | 186 | if @vol == 0 187 | @pdf.ibox 0.85, 2.80, 0.25, 16.60, "QUANTIDADE" 188 | @pdf.ibox 0.85, 5.00, 3.05, 16.60, "ESPÉCIE" 189 | @pdf.ibox 0.85, 3.05, 8.05, 16.60, "MARCA" 190 | @pdf.ibox 0.85, 3.00, 11.10, 16.60, "NUMERAÇÃO" 191 | @pdf.ibox 0.85, 3.43, 14.10, 16.60, "PESO BRUTO" 192 | @pdf.ibox 0.85, 3.30, 17.53, 16.60, "PESO LÍQUIDO" 193 | else 194 | @pdf.ibox 0.85, 2.80, 0.25, 16.60, "QUANTIDADE", (quantidade.round == quantidade ? quantidade.to_i : quantidade).to_s 195 | @pdf.ibox 0.85, 5.00, 3.05, 16.60, "ESPÉCIE", especie 196 | @pdf.ibox 0.85, 3.05, 8.05, 16.60, "MARCA", marca 197 | @pdf.ibox 0.85, 3.00, 11.10, 16.60, "NUMERAÇÃO" 198 | @pdf.inumeric 0.85, 3.43, 14.10, 16.60, "PESO BRUTO", peso_bruto.to_s, {:decimals => 3} 199 | @pdf.inumeric 0.85, 3.30, 17.53, 16.60, "PESO LÍQUIDO", peso_liquido.to_s, {:decimals => 3} 200 | end 201 | end 202 | 203 | def render_cabecalho_dos_produtos(page_number) 204 | base_y = page_number == 1 ? 17.45 : 8.2 205 | height = page_number == 1 ? 6.70 : 17.2 206 | 207 | @pdf.ititle 0.42, 10.00, 0.25, base_y, "DADOS DO PRODUTO / SERVIÇO" 208 | 209 | @pdf.ibox height, 2.00, 0.25, base_y + 0.42, "CÓDIGO" 210 | @pdf.ibox height, 4.90, 2.25, base_y + 0.42, "DESCRIÇÃO" 211 | @pdf.ibox height, 1.30, 7.15, base_y + 0.42, "NCM" 212 | @pdf.ibox height, 0.80, 8.45, base_y + 0.42, "CST" 213 | @pdf.ibox height, 1.00, 9.25, base_y + 0.42, "CFOP" 214 | @pdf.ibox height, 1.00, 10.25, base_y + 0.42, "UNID" 215 | @pdf.ibox height, 1.30, 11.25, base_y + 0.42, "QUANT" 216 | @pdf.ibox height, 1.50, 12.55, base_y + 0.42, "VALOR UNIT" 217 | @pdf.ibox height, 1.50, 14.05, base_y + 0.42, "VALOR TOT" 218 | @pdf.ibox height, 1.50, 15.55, base_y + 0.42, "BASE CÁLC" 219 | @pdf.ibox height, 1.00, 17.05, base_y + 0.42, "VL ICMS" 220 | @pdf.ibox height, 1.00, 18.05, base_y + 0.42, "VL IPI" 221 | @pdf.ibox height, 0.90, 19.05, base_y + 0.42, "% ICMS" 222 | @pdf.ibox height, 0.86, 19.95, base_y + 0.42, "% IPI" 223 | end 224 | 225 | def render_calculo_do_issqn 226 | @pdf.ititle 0.42, 10.00, 0.25, 24.64, "CÁLCULO DO ISSQN" 227 | 228 | @pdf.ibox 0.85, 5.08, 0.25, 25.06, "INSCRIÇÃO MUNICIPAL", @xml['emit/IM'] 229 | @pdf.ibox 0.85, 5.08, 5.33, 25.06, "VALOR TOTAL DOS SERVIÇOS", @xml['total/vServ'].empty? ? @xml['total/ISSQNtot/vServ'] : @xml['total/vServ'] 230 | @pdf.ibox 0.85, 5.08, 10.41, 25.06, "BASE DE CÁLCULO DO ISSQN", @xml['total/vBCISS'].empty? ? @xml['total/ISSQNtot/vBC'] : @xml['total/vBCISS'] 231 | @pdf.ibox 0.85, 5.28, 15.49, 25.06, "VALOR DO ISSQN", @xml['total/ISSTot'].empty? ? @xml['total/ISSQNtot/vISS'] : @xml['total/ISSTot'] 232 | end 233 | 234 | def render_dados_adicionais_box 235 | @pdf.ititle 0.42, 10.00, 0.25, 25.91, "DADOS ADICIONAIS" 236 | @pdf.ibox 3.07, 12.93, 0.25, 26.33, "INFORMAÇÕES COMPLEMENTARES", '', {:size => 8, :valign => :top} 237 | 238 | @pdf.ibox 3.07, 7.62, 13.17, 26.33, "RESERVADO AO FISCO" 239 | end 240 | 241 | def render_dados_adicionais 242 | info_adicional = "" 243 | 244 | if @vol > 1 245 | info_adicional += "TRANSPORTADOR/VOLUMES TRANSPORTADOS\n" 246 | 247 | y = 26.67 248 | info_adicional += @xml.inject 'xmlns', 'vol', "" do |info, det| 249 | y = y + 0.15 250 | 251 | info + 252 | "QUANT.: #{det.css('qVol').text} " + 253 | "ESPÉCIE: #{det.css('esp').text} " + 254 | "MARCA: #{det.css('marca').text} " + 255 | "PESO B.: #{det.css('pesoB').text} " + 256 | "PESO LÍQ.: #{det.css('pesoL').text}\n" 257 | end 258 | 259 | info_adicional += "\nOUTRAS INFORMAÇÕES: " 260 | end 261 | 262 | info_adicional += @xml['infAdic/infCpl'] 263 | 264 | if @xml.css('entrega') 265 | info_adicional += " LOCAL DA ENTREGA: " + 266 | @xml['entrega/xLgr'] + " " + 267 | @xml['entrega/nro'] + " " + 268 | "Bairro/Distrito: " + @xml['entrega/xBairro'] + " " + 269 | "Municipio: " + @xml['entrega/xMun'] + " " + 270 | "UF: " + @xml['entrega/UF'] + " " + 271 | "País: Brasil" 272 | end 273 | 274 | if @xml['infAdic/infAdFisco'] != "" 275 | info_adicional += "\n#{@xml['infAdic/infAdFisco']}" 276 | end 277 | 278 | @pdf.bounding_box [(0.33).cm, Helper.invert(26.78.cm)], height: 2.7.cm, width: 12.7.cm do 279 | @pdf.font_size 6 280 | @pdf.text info_adicional, align: :justify 281 | end 282 | end 283 | 284 | def render_produtos 285 | @pdf.font_size(6) do 286 | @produtos_box = @pdf.itable 6.37, 21.50, 0.25, 18.17, 287 | @xml.collect('xmlns', 'det') { |det| 288 | [ 289 | det.css('prod/cProd').text, #I02 290 | Descricao.generate(det), #I04 291 | #{}" ", 292 | det.css('prod/NCM').text, #I05 293 | Cst.to_danfe(det), #N11 294 | det.css('prod/CFOP').text, #I08 295 | det.css('prod/uCom').text, #I09 296 | Helper.format_quantity(det.css('prod/qCom').text), 297 | Helper.numerify(det.css('prod/vUnCom').text), #I10a 298 | Helper.numerify(det.css('prod/vProd').text), #I11 299 | Helper.numerify_default_zero(det.css('ICMS/*/vBC').text), #N15 300 | Helper.numerify_default_zero(det.css('ICMS/*/vICMS').text), #N17 301 | Helper.numerify_default_zero(det.css('IPI/*/vIPI').text), #O14 302 | Helper.numerify_default_zero(det.css('ICMS/*/pICMS').text), #N16 303 | Helper.numerify_default_zero(det.css('IPI/*/pIPI').text) #O13 304 | ] 305 | }, 306 | :column_widths => { 307 | 0 => 2.00.cm, 308 | 1 => 4.90.cm, 309 | 2 => 1.30.cm, 310 | 3 => 0.80.cm, 311 | 4 => 1.00.cm, 312 | 5 => 1.00.cm, 313 | 6 => 1.30.cm, 314 | 7 => 1.50.cm, 315 | 8 => 1.50.cm, 316 | 9 => 1.50.cm, 317 | 10 => 1.00.cm, 318 | 11 => 1.00.cm, 319 | 12 => 0.90.cm, 320 | 13 => 0.86.cm 321 | }, 322 | :cell_style => {:padding => 2, :border_width => 0} do |table| 323 | table.column(6..13).style(:align => :right) 324 | table.column(0..13).border_width = 1 325 | table.column(0..13).borders = [:top] 326 | table.before_rendering_page do |page| 327 | if @pdf.page_number == 1 328 | @pdf.bounds.instance_variable_set(:@y, (22.2).cm) 329 | @pdf.bounds.instance_variable_set(:@height, (16.8).cm) 330 | else 331 | @pdf.bounds.instance_variable_set(:@y, (21).cm) 332 | end 333 | end 334 | end 335 | end 336 | end 337 | 338 | def descricao_modalidade_frete(modalidade) 339 | case modalidade 340 | when '1' 341 | "1 - Destinatário (FOB)" 342 | when '2' 343 | "2- Terceiros" 344 | when '3' 345 | "3- Remetente (Transp. Próprio)" 346 | when '4' 347 | "4- Remetente (Transp.Dest)" 348 | when '9' 349 | "9 - Sem frete" 350 | else 351 | "0 - Remetente (CIF)" 352 | end 353 | end 354 | end 355 | end 356 | -------------------------------------------------------------------------------- /lib/ruby_danfe/danfe_nfce_generator.rb: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | require 'digest/sha1' 3 | 4 | module RubyDanfe 5 | class DanfeNfceGenerator 6 | def initialize(xml) 7 | @xml = xml 8 | @pdf = Document.new(page_size: [390, 845]) 9 | end 10 | 11 | def generatePDF 12 | @pdf.repeat :all do 13 | render_cabecalho 14 | render_info_fixas 15 | render_detalhes_venda 16 | render_totais 17 | render_tributos 18 | render_mensagem_fiscal 19 | render_consumidor 20 | render_qrcode 21 | end 22 | 23 | render_produtos 24 | 25 | @pdf 26 | end 27 | 28 | private 29 | def render_cabecalho 30 | 31 | # ibox(h, w, x, y, title = '', info = '', options = {}) 32 | 33 | @pdf.ibox 3, 12, 0.9, 1 34 | 35 | @pdf.ibox 2.85, 3, 1.5, 2, "", "NFC-e", {:size => 12, :align => :center, :border => 0, :style => :bold} 36 | 37 | @pdf.ibox 4.92, 7, 4, 0, '', 38 | @xml['emit/xNome'] + "\n" + 39 | "CNPJ: " + @xml['emit/CNPJ'] + "\n" + 40 | @xml['enderEmit/xLgr'] + ", " + @xml['enderEmit/nro'] + "\n" + 41 | @xml['enderEmit/xBairro']+ " " + "-" + " " + @xml['enderEmit/xMun'] + "/" + @xml['enderEmit/UF'] + "\n" + 42 | "Fone: " + @xml['enderEmit/fone'] + "\n" + 43 | "CEP: " + @xml['enderEmit/CEP'] + " - " + "IE: " + @xml['emit/IE'], {:align => :center, :valign => :center, size: 8, border: 0} 44 | end 45 | 46 | def render_info_fixas 47 | @pdf.ibox 2, 12, 0.9, 4, '', 48 | "DANFE NFC-e - Documento Auxiliar da Nota Fiscal Eletrônica" + "\n" + "para Consumidor Final" + "\n \n" + 49 | "Não permite aproveitamento de crédito de ICMS", {align: :center, :valign => :center, size: 8} 50 | end 51 | 52 | def render_detalhes_venda 53 | render_cabecalho_dos_produtos 54 | 55 | totais = @xml.css('total') 56 | 57 | @pdf.inumeric 0.70, 4, 0.9, 15.8, "Subtotal", totais.css('vProd').text, {:size => 6} 58 | @pdf.inumeric 0.70, 4, 4.9, 15.8, "Desconto", totais.css('vDesc').text, {:size => 6} 59 | @pdf.inumeric 0.70, 4, 8.9, 15.8, "Troco", totais.css('vTroco').text, {:size => 6} 60 | end 61 | 62 | def render_cabecalho_dos_produtos 63 | @pdf.ibox 9.55, 1.3, 0.9, 6.1, "CÓDIGO", "",{:size => 8, :align => :center, :style => :bold} 64 | @pdf.ibox 9.55, 1.3, 2.2, 6.1, "UNIDADE" 65 | @pdf.ibox 9.55, 5.1, 3.5, 6.1, "DESCRIÇÃO" 66 | @pdf.ibox 9.55, 1.3, 8.6, 6.1, "QUANT" 67 | @pdf.ibox 9.55, 1.5, 9.9, 6.1, "VALOR UNIT" 68 | @pdf.ibox 9.55, 1.5, 11.4, 6.1, "VALOR TOTAL" 69 | 70 | @pdf.horizontal_line 26, 365, at: 630 71 | end 72 | 73 | def render_produtos 74 | @pdf.font_size(6) do 75 | @pdf.itable 9.37, 21.50, 0.9, 6.6, 76 | @xml.collect('xmlns', 'det') { |det| 77 | [ 78 | det.css('prod/cProd').text, # CÓDIGO 79 | det.css('prod/uCom').text, # UNIDADE 80 | det.css('prod/xProd').text, # DESCRICAO 81 | Helper.numerify(det.css('prod/qCom').text), # QUANTIDADE 82 | Helper.numerify(det.css('prod/vUnCom').text), # VALOR UNIT 83 | Helper.numerify(det.css('prod/vProd').text), # VALOR TOTAL 84 | ] 85 | }, 86 | :column_widths => { 87 | 0 => 1.30.cm, 88 | 1 => 1.30.cm, 89 | 2 => 5.10.cm, 90 | 3 => 1.30.cm, 91 | 4 => 1.50.cm, 92 | 5 => 1.50.cm 93 | }, 94 | :cell_style => {:padding => 2, :border_width => 0} do |table| 95 | table.column(6..13).style(:align => :right) 96 | table.column(0..13).border_width = 1 97 | table.column(0..13).borders = [:bottom] 98 | end 99 | end 100 | end 101 | 102 | def get_produtos(produto, row = []) 103 | row << produto.css('cProd').text 104 | row << produto.css('uCom').text 105 | row << produto.css('xProd').text 106 | row << produto.css('qCom').text 107 | row << produto.css('vUnCom').text 108 | row << produto.css('vProd').text 109 | return row 110 | end 111 | 112 | def render_totais 113 | qtde_produtos = @xml.css('det').count 114 | forma_pgto = get_forma_pgto 115 | valor_total = Helper.numerify(@xml.css('total').css('vProd').text) 116 | vlr_pago = Helper.numerify(@xml.css('vPag').text) 117 | 118 | @pdf.ibox 2, 12, 0.9, 16.7, '', 119 | "QTD. TOTAL DE ITENS: #{qtde_produtos}" + "\n" + "FORMA DE PAGAMENTO: #{forma_pgto}" + "\n" + "VALOR TOTAL (R$): #{valor_total}" + "\n" + "VALOR PAGO (R$): #{vlr_pago}", {align: :right, valign: :right, size: 6, border: 0, style: :bold} 120 | end 121 | 122 | def get_forma_pgto 123 | cod_forma_pgto = @xml.css('tPag').text 124 | case cod_forma_pgto 125 | when "01" then "Dinheiro" 126 | when "02" then "Cheque" 127 | when "03" then "Cartão de Crédito" 128 | when "04" then "Cartão de Débito" 129 | when "05" then "Crédito Loja" 130 | when "10" then "Vale Alimentação" 131 | when "11" then "Vale Refeição" 132 | when "12" then "Vale Presente" 133 | when "13" then "Vale Combustível" 134 | when "99" then "Outros" 135 | end 136 | end 137 | 138 | def render_tributos 139 | totais = @xml.css('total') 140 | soma_tributos = totais.css('vII').text.to_f + totais.css('vIPI').text.to_f + totais.css('vIPI').text.to_f + totais.css('vPIS').text.to_f 141 | + totais.css('vCOFINS').text.to_f + totais.css('vOutro').text.to_f 142 | 143 | @pdf.ibox 0.9, 12, 0.9, 18, 'Tributos', 144 | "Informação dos Tributos Totais Incidentes (Lei Federal 12.741 /2012): #{soma_tributos}", {align: :center, :valign => :center, size: 7} 145 | end 146 | 147 | def render_mensagem_fiscal 148 | numero_nota = @xml.css('nNF').text 149 | serie = @xml.css('serie').text 150 | data = @xml.css('dhEmi').text 151 | data_emissao = Date.parse(data).strftime('%d/%m/%Y %I:%M:%S') 152 | 153 | chave_acesso = get_chave 154 | cabecalho = "" 155 | 156 | tipo_emissao = @xml.css('tpEmis') 157 | if tipo_emissao != nil && tipo_emissao.text != "1" 158 | cabecalho = "EMITIDA EM CONTINGENCIA" + "\n \n" 159 | end 160 | 161 | @pdf.ibox 3, 12, 0.9, 18.9, 'Mensagem Fiscal', 162 | "#{cabecalho}" + 163 | "Número #{numero_nota} | Série #{serie} | Emissão #{data_emissao} - Via Consumidor" + 164 | "\n \n" + "Consulte pela Chave de Acesso em #{get_url_consulta}" + 165 | "\n \n" + "CHAVE DE ACESSO:" + 166 | "\n \n" + chave_acesso + "\n", {align: :center, :valign => :center, size: 7} 167 | end 168 | 169 | def get_chave 170 | chave = @xml.css('infNFe').attr("Id").value.gsub(/^(NFe|CTe)/, "") 171 | return "%s %s %s %s %s %s %s %s %s %s %s" %[chave[0..3], chave[4..7], chave[8..11], chave[12..15], chave[16..19], chave[20..23], chave[24..27], chave[28..31], chave[32..35], chave[36..39], chave[40..43]] 172 | end 173 | 174 | def render_consumidor 175 | consumidor = @xml.xpath("//dest") 176 | nome = @xml.regex_string(consumidor.to_s.downcase, "//xnome").text.split.map(&:capitalize).join(' ') 177 | 178 | endereco = @xml.regex_string(consumidor.to_s.downcase, "//xlgr").text + " - " + @xml.regex_string(consumidor.to_s.downcase, "//xbairro").text 179 | endereco += " - " + @xml.regex_string(consumidor.to_s.downcase, "//xmun").text + " - " + @xml.regex_string(consumidor.to_s.downcase, "//uf").text.downcase 180 | endereco = endereco.split.map(&:capitalize).join(' ') 181 | endereco = endereco.upcase 182 | 183 | if consumidor.any? 184 | documento = @xml.css('dest idEstrangeiro, dest CPF, dest CNPJ').text 185 | tipo_documento, documento = 186 | case documento.length 187 | when 11 then ["CPF", "%s.%s.%s-%s" % documento.match(/(...)(...)(...)(..)/).captures] 188 | when 14 then ["CNPJ", "%s.%s.%s/%s-%s" % documento.match(/(..)(...)(...)(....)(..)/).captures] 189 | else ["ID Estrangeiro", documento] 190 | end 191 | 192 | consumidor_msg = nome 193 | consumidor_msg += " - #{tipo_documento}: #{documento}" 194 | consumidor_msg += "\n" + endereco 195 | else 196 | consumidor_msg = "CONSUMIDOR NÃO IDENTIFICADO" 197 | end 198 | 199 | @pdf.ibox 1.3, 12, 0.9, 21.9, 'Consumidor', 200 | consumidor_msg, {align: :center, :valign => :top, size: 7} 201 | end 202 | 203 | def render_qrcode 204 | @pdf.iqrcode 5.18, 28, get_qrcode_url, 20 205 | 206 | data = @xml.css('dhRecbto').text 207 | data_receb = Date.parse(data).strftime('%d/%m/%Y %I:%M:%S') 208 | 209 | protocolo = @xml.css('nProt').text 210 | msg_protocolo = "Protocolo de Autorização: #{protocolo} - Data: #{data_receb}" 211 | 212 | @pdf.ibox 0.7, 12, 0.9, 23.3, '', msg_protocolo, size: 6, align: :center, valign: :center 213 | end 214 | 215 | def get_qrcode_url 216 | ender_consulta = get_ender_consulta 217 | end 218 | 219 | def get_ender_consulta 220 | url = get_url_qr_code 221 | 222 | params = { 223 | "chNFe" => get_chave.gsub(/ /, ""), 224 | "nVersao" => @xml.css('nfeProc').attr("versao"), 225 | "tpAmb" => @xml['ide/tpAmb'], 226 | "dhEmi" => str_to_hex(@xml['ide/dhEmi']), 227 | "vNF" => @xml['ICMSTot/vNF'], 228 | "vICMS" => @xml['ICMSTot/vICMS'], 229 | "digVal" => str_to_hex(@xml['nfe/DigestValue']), 230 | "cIdToken" => '000001', 231 | } 232 | 233 | unless @xml.css('dest').empty? 234 | params["cDest"] = @xml.css('dest idEstrangeiro, dest CPF, dest CNPJ').text 235 | end 236 | 237 | params_string = params.to_a.map{|p| p.join("=")}.join("&") 238 | 239 | hash_token = Digest::SHA1.base64digest params_string 240 | 241 | url + params_string + "&cHashQRCode=" + hash_token 242 | end 243 | 244 | def get_url_qr_code 245 | case @xml.css('emit').css('UF').text.upcase 246 | when "AC" then "http://www.sefaznet.ac.gov.br/nfe/NFe.jsp?opc=3" 247 | when "AM" then "http://sistemas.sefaz.am.gov.br/nfceweb/consultarNFCe.jsp?" 248 | when "MA" then "http://www.nfce.sefaz.ma.gov.br/portal/consultarNFCe.jsp?" 249 | when "MT" then "http://www.sefaz.mt.gov.br/nfe/portal/consultanfce?" 250 | when "RN" then "http://www.nfe.rn.gov.br/portal/consultarNFCe.jsp?" 251 | when "RO" then "http://www.nfce.sefin.ro.gov.br/consultanfce/consulta.jsp?" 252 | when "RS" then "https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx?" 253 | when "SE" then "http://www.nfe.se.gov.br/portal/consultarNFCe.jsp?" 254 | end 255 | end 256 | 257 | def get_url_consulta 258 | case @xml.css('emit').css('UF').text.upcase 259 | when "AC" then "http://www.sefaznet.ac.gov.br/nfe/NFe.jsp?opc=3" 260 | when "AM" then "http://sistemas.sefaz.am.gov.br/nfceweb/consultarNFCe.jsp" 261 | when "MA" then "http://www.nfce.sefaz.ma.gov.br/portal/consultarNFCe.jsp" 262 | when "MT" then "http://www.sefaz.mt.gov.br/nfe/portal/consultanfce" 263 | when "RN" then "http://www.nfe.rn.gov.br/portal/consultarNFCe.jsp" 264 | when "RO" then "http://www.nfce.sefin.ro.gov.br" 265 | when "RS" then "https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx" 266 | when "SE" then "http://www.nfe.se.gov.br/portal/consultarNFCe.jsp" 267 | end 268 | end 269 | 270 | def str_to_hex str 271 | str.split("").reduce("") do |str, char| 272 | str + char.ord.to_s(16) 273 | end 274 | end 275 | end 276 | end 277 | -------------------------------------------------------------------------------- /lib/ruby_danfe/danfse_generator.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | module RubyDanfe 3 | class DanfseGenerator 4 | def initialize(xml) 5 | @xml = xml 6 | @pdf = Document.new 7 | @vol = 0 8 | end 9 | 10 | attr_reader :municipios 11 | 12 | def municipios 13 | lib_path = File.expand_path("../../", __FILE__) 14 | @municipios ||= JSON.parse(File.read(File.join(lib_path, 'municipios.json'))) 15 | end 16 | 17 | def generatePDF 18 | render_titulo 19 | render_prestador 20 | render_tomador 21 | render_intermediario 22 | render_discriminacao 23 | render_valor_total 24 | render_outras 25 | @pdf 26 | end 27 | 28 | private 29 | def render_titulo 30 | @pdf.ibox 2.55, 16.10, 0.25, 0.42, '', 31 | "PREFEITURA DO MUNICÍPIO DE #{municipios[@xml['InfNfse/PrestadorServico/Endereco/CodigoMunicipio']].upcase} \n" + 32 | "Secretaria Municipal da Fazenda \n" + 33 | "NOTA FISCAL ELETRÔNICA DE SERVIÇOS - NFS-e \n" + 34 | "RPS n° #{@xml['IdentificacaoRps/Numero']}, emitido em #{@xml['DataEmissaoRps']}", {:align => :center, :valign => :center} 35 | 36 | @pdf.ibox 0.85, 4.47, 16.35, 0.42, "NÚMERO DA NOTA", "#{@xml['InfNfse/Numero'].rjust(8,'0')}" 37 | @pdf.ibox 0.85, 4.47, 16.35, 1.27, "DATA E HORA DE EMISSÃO", "#{@xml['InfNfse/DataEmissao'].gsub('T', ' ')}" 38 | @pdf.ibox 0.85, 4.47, 16.35, 2.12, "CÓDIGO DE VERIFICAÇÃO", "#{@xml['CodigoVerificacao']}" 39 | end 40 | 41 | def render_prestador 42 | @pdf.ibox 4.25, 20.57, 0.25, 2.97 43 | @pdf.ibox 0.85, 20.57, 0.25, 2.97, '', 'PRESTADOR DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center} 44 | @pdf.ibox 0.85, 20.57, 0.25, 3.82, "Nome/Razão Social", "#{@xml['PrestadorServico/RazaoSocial']}", {border: 0} 45 | @pdf.ibox 0.85, 12, 0.25, 4.67, "CPF/CNPJ", "#{@xml['PrestadorServico/IdentificacaoPrestador/Cnpj'] || @xml['PrestadorServico/IdentificacaoPrestador/Cpf']}", {border: 0} 46 | @pdf.ibox 0.85, 4.47, 12, 4.67, "Inscrição Municipal", "#{@xml['IdentificacaoPrestador/InscricaoMunicipal']}", {border: 0} 47 | @pdf.ibox 0.85, 20.57, 0.25, 5.52, "Endereço", "#{@xml['PrestadorServico/Endereco/Endereco']}", {border: 0} 48 | @pdf.ibox 0.85, 10, 0.25, 6.37, "Município", "#{municipios[@xml['PrestadorServico/Endereco/CodigoMunicipio']]}", {border: 0} 49 | @pdf.ibox 0.85, 4.47, 10, 6.37, "UF", "#{@xml['PrestadorServico/Endereco/Uf']}", {border: 0} 50 | @pdf.ibox 0.85, 4.47, 15, 6.37, "E-mail", "#{@xml['PrestadorServico/Contato/Email']}", {border: 0} 51 | end 52 | 53 | def render_tomador 54 | @pdf.ibox 4.25, 20.57, 0.25, 7.22 55 | @pdf.ibox 0.85, 20.57, 0.25, 7.22, '', 'TOMADOR DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center} 56 | @pdf.ibox 0.85, 20.57, 0.25, 8.07, "Nome/Razão Social", "#{@xml['TomadorServico/RazaoSocial']}", {border: 0} 57 | @pdf.ibox 0.85, 12, 0.25, 8.92, "CPF/CNPJ", "#{@xml['TomadorServico/IdentificacaoTomador/CpfCnpj/Cnpj'] || @xml['TomadorServico/IdentificacaoTomador/CpfCnpj/Cpf']}", {border: 0} 58 | @pdf.ibox 0.85, 4.47, 12, 8.92, "Inscrição Municipal", "#{@xml['IdentificacaoTomador/InscricaoMunicipal']}", {border: 0} 59 | @pdf.ibox 0.85, 20.57, 0.25, 9.77, "Endereço", "#{@xml['TomadorServico/Endereco/Endereco']}", {border: 0} 60 | @pdf.ibox 0.85, 10, 0.25, 10.62, "Município", "#{municipios[@xml['TomadorServico/Endereco/CodigoMunicipio']]}", {border: 0} 61 | @pdf.ibox 0.85, 4.47, 10, 10.62, "UF", "#{@xml['TomadorServico/Endereco/Uf']}", {border: 0} 62 | @pdf.ibox 0.85, 4.47, 15, 10.62, "E-mail", "#{@xml['TomadorServico/Contato/Email']}", {border: 0} 63 | end 64 | 65 | def render_intermediario 66 | @pdf.ibox 1.70, 20.57, 0.25, 11.47 67 | @pdf.ibox 0.85, 20.57, 0.25, 11.47, '', 'INTERMEDIÁRIO DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center} 68 | @pdf.ibox 0.85, 12, 0.25, 12.32, "Nome/Razão Social", "#{@xml['IdentificacaoIntermediarioServico/RazaoSocial']}", {border: 0} 69 | @pdf.ibox 0.85, 8, 12.25, 12.32, "CPF/CNPJ", "#{@xml['IdentificacaoIntermediarioServico/CpfCnpj/Cnpj'] || @xml['IdentificacaoIntermediarioServico/CpfCnpj/Cpf']}", {border: 0} 70 | end 71 | 72 | def render_discriminacao 73 | @pdf.ibox 9.35, 20.57, 0.25, 13.17 74 | @pdf.ibox 0.85, 20.57, 0.25, 13.17, '', 'DISCRIMINAÇÃO DOS SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center} 75 | @pdf.ibox 8, 19.57, 0.75, 14.02, "", "#{@xml['Servico/Discriminacao']}", {border: 0} 76 | end 77 | 78 | def render_valor_total 79 | @pdf.ibox 1.70, 20.57, 0.25, 22.52 80 | @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} 81 | @pdf.inumeric 0.85, 4.06, 0.25, 23.37, "INSS", @xml['Servico/Valores/ValorInss'] 82 | @pdf.inumeric 0.85, 4.06, 4.31, 23.37, "IRRF", @xml['Servico/Valores/ValorIr'] 83 | @pdf.inumeric 0.85, 4.06, 8.37, 23.37, "CSLL", @xml['Servico/Valores/ValorCsll'] 84 | @pdf.inumeric 0.85, 4.06, 12.43, 23.37, "COFINS", @xml['Servico/Valores/ValorCofins'] 85 | @pdf.inumeric 0.85, 4.32, 16.49, 23.37, "PIS/PASEP", @xml['Servico/Valores/ValorPis'] 86 | @pdf.ibox 0.85, 20.57, 0.25, 24.22, "Código do Serviço", @xml['Servico/CodigoTributacaoMunicipio'] 87 | @pdf.inumeric 0.85, 3.46, 0.25, 25.07, "Valor Total das Deduções", @xml['Servico/Valores/ValorDeducoes'] 88 | @pdf.inumeric 0.85, 3.46, 3.71, 25.07 , "Base de Cálculo", @xml['Servico/Valores/BaseCalculo'] 89 | @pdf.ibox 0.85, 3.46, 7.17, 25.07, "Alíquota", @xml['Servico/Valores/Aliquota'] 90 | @pdf.inumeric 0.85, 3.46, 10.63, 25.07, "Valor do ISS", @xml['Servico/Valores/ValorIss'] 91 | @pdf.inumeric 0.85, 6.73, 14.09, 25.07, "Crédito", @xml['InfNfse/ValorCredito'] 92 | @pdf.ibox 0.85, 10.38, 0.25, 25.92, "Muncípio da Prestação do Serviço", municipios[@xml['OrgaoGerador/CodigoMunicipio']], :style => :bold 93 | @pdf.ibox 0.85, 10.19, 10.63, 25.92, "Número Inscrição da Obra", @xml['DadosConstrucaoCivil/CodigoObra'], :style => :bold 94 | end 95 | 96 | def render_outras 97 | @pdf.ibox 2.55, 20.57, 0.25, 26.77 98 | @pdf.ibox 0.85, 20.57, 0.25, 26.77, '', 'OUTRAS INFORMAÇÕES', {border: 0, style: :bold,:align => :center, :valign => :center} 99 | @pdf.ibox 1.70, 19.57, 0.75, 27.62, "", "#{@xml['InfNfse/OutrasInformacoes']}", {border: 0} 100 | end 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /lib/ruby_danfe/descricao.rb: -------------------------------------------------------------------------------- 1 | #encoding: utf-8 2 | 3 | module RubyDanfe 4 | class Descricao 5 | LINEBREAK = "\n" 6 | 7 | def self.generate(det) 8 | descricao = "#{det.css('prod/xProd').text}" 9 | 10 | if need_infAdProd(det) 11 | descricao += LINEBREAK 12 | descricao += det.css('infAdProd').text 13 | end 14 | 15 | if need_fci(det) 16 | descricao += LINEBREAK 17 | descricao += "FCI: #{det.css('prod/nFCI').text}" 18 | end 19 | 20 | if need_veicProd(det) 21 | veicProd = det.css('veicProd') 22 | 23 | descricao += LINEBREAK 24 | descricao += "Chassi: #{veicProd.css('chassi').text} " 25 | descricao += "Motor: #{veicProd.css('nMotor').text} " 26 | descricao += "AnoFab: #{veicProd.css('anoFab').text} " 27 | descricao += "AnoMod: #{veicProd.css('anoMod').text} " 28 | descricao += "Cor: #{veicProd.css('xCor').text}" 29 | end 30 | 31 | if need_st(det) 32 | descricao += LINEBREAK 33 | descricao += "ST: MVA: #{det.css('ICMS/*/pMVAST').text}% " 34 | descricao += "* Alíq: #{det.css('ICMS/*/pICMSST').text}% " 35 | descricao += "* BC: #{det.css('ICMS/*/vBCST').text} " 36 | descricao += "* Vlr: #{det.css('ICMS/*/vICMSST').text}" 37 | end 38 | 39 | descricao 40 | end 41 | 42 | private 43 | def self.need_infAdProd(det) 44 | !det.css('infAdProd').text.empty? 45 | end 46 | 47 | def self.need_fci(det) 48 | !det.css('prod/nFCI').text.empty? 49 | end 50 | 51 | def self.need_veicProd(det) 52 | !det.css('prod/veicProd').text.empty? 53 | end 54 | 55 | def self.need_st(det) 56 | det.css('ICMS/*/vBCST').text.to_i > 0 57 | end 58 | 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/ruby_danfe/document.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | class Document 3 | def initialize(opts = {}) 4 | default_opts = { 5 | :page_size => 'A4', 6 | :page_layout => :portrait, 7 | :left_margin => 0, 8 | :right_margin => 0, 9 | :top_margin => 0, 10 | :botton_margin => 0 11 | } 12 | 13 | @document = Prawn::Document.new(default_opts.merge(opts)) 14 | 15 | @document.font "Times-Roman" 16 | end 17 | 18 | def method_missing(method_name, *args, &block) 19 | @document.send(method_name, *args, &block) 20 | end 21 | 22 | def respond_to_missing?(method_name, include_private = false) 23 | @document.respond_to?(method_name, include_private) || super 24 | end 25 | 26 | def ititle(h, w, x, y, title) 27 | self.text_box title, :size => 10, :at => [x.cm, Helper.invert(y.cm) - 2], :width => w.cm, :height => h.cm, :style => :bold 28 | end 29 | 30 | def ibarcode(h, w, x, y, info) 31 | info = info.gsub(/\D/, '') 32 | Barby::Code128C.new(info).annotate_pdf(self, :x => x.cm, :y => Helper.invert(y.cm), :width => w.cm, :height => h.cm) if info != '' 33 | end 34 | 35 | def iqrcode(x, y, info, size = nil) 36 | Barby::QrCode.new(info, :level => :q, :size => size).annotate_pdf(self, :x => x.cm, :y => Helper.invert(y.cm)) if info != '' 37 | end 38 | 39 | def irectangle(h, w, x, y) 40 | self.stroke_rectangle [x.cm, Helper.invert(y.cm)], w.cm, h.cm 41 | end 42 | 43 | def ibox(h, w, x, y, title = '', info = '', options = {}) 44 | box [x.cm, Helper.invert(y.cm)], w.cm, h.cm, title, info, options 45 | end 46 | 47 | def idate(h, w, x, y, title = '', info = '', options = {}) 48 | tt = info.gsub(/T.*/, '').split('-') 49 | ibox h, w, x, y, title, "#{tt[2]}/#{tt[1]}/#{tt[0]}", options 50 | end 51 | 52 | def box(at, w, h, title = '', info = '', options = {}) 53 | options = { 54 | :align => :left, 55 | :size => 10, 56 | :style => nil, 57 | :valign => :top, 58 | :border => 1 59 | }.merge(options) 60 | self.stroke_rectangle at, w, h if options[:border] == 1 61 | self.text_box title, :size => 6, :style => :italic, :at => [at[0] + 2, at[1] - 2], :width => w - 4, :height => 8 if title != '' 62 | 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] 63 | end 64 | 65 | def inumeric(h, w, x, y, title = '', info = '', options = {}) 66 | numeric [x.cm, Helper.invert(y.cm)], w.cm, h.cm, title, info, options 67 | end 68 | 69 | def numeric(at, w, h, title = '', info = '', options = {}) 70 | options = {:decimals => 2}.merge(options) 71 | info = Helper.numerify(info, options[:decimals]) if info != '' 72 | box at, w, h, title, info, options.merge({:align => :right}) 73 | end 74 | 75 | def itable(h, w, x, y, data, options = {}, &block) 76 | self.bounding_box [x.cm, Helper.invert(y.cm)], :width => w.cm, :height => h.cm do 77 | self.table data, options do |table| 78 | yield(table) 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/ruby_danfe/helper.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | class Helper 3 | def self.numerify(number, decimals = 2) 4 | number = number.tr("\n","").delete(" ") 5 | return "" if !number || number == "" 6 | int, frac = ("%.#{decimals}f" % number).split(".") 7 | int.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1\.") 8 | int + "," + frac 9 | rescue 10 | number 11 | end 12 | 13 | def self.numerify_default_zero(number, decimals = 2) 14 | number = number.tr("\n","").delete(" ") 15 | return "0,00" if !number || number == "" 16 | int, frac = ("%.#{decimals}f" % number).split(".") 17 | int.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1\.") 18 | int + "," + frac 19 | rescue 20 | number 21 | end 22 | 23 | def self.invert(y) 24 | 28.7.cm - y 25 | end 26 | 27 | def self.format_quantity(qty) 28 | return Helper.numerify(qty, RubyDanfe.options.quantity_decimals) if RubyDanfe.options.numerify_prod_qcom 29 | qty.gsub!(",", ".") 30 | qty[qty.rindex('.')] = ',' if qty.rindex('.') 31 | qty 32 | end 33 | 34 | def self.format_datetime(string) 35 | formated_datetime = "" 36 | 37 | if not string.empty? 38 | date = extract_date_time(string) 39 | formated_datetime = date.strftime("%d/%m/%Y %H:%M:%S") 40 | end 41 | 42 | formated_datetime 43 | end 44 | 45 | def self.format_date(string) 46 | formated_date = "" 47 | 48 | if not string.empty? 49 | date = Date.strptime(string, "%Y-%m-%d") 50 | formated_date = date.strftime("%d/%m/%Y") 51 | end 52 | 53 | formated_date 54 | end 55 | 56 | def self.format_time(string) 57 | formated_time = "" 58 | 59 | if not string.empty? 60 | time = Time.strptime(string, "%H:%M:%S") 61 | formated_time = time.strftime("%H:%M:%S") 62 | end 63 | 64 | formated_time 65 | end 66 | 67 | def self.extract_time_from_date(string) 68 | formated_time = "" 69 | 70 | if not string.empty? 71 | date = extract_date_time(string) 72 | formated_time = date.strftime("%H:%M:%S") 73 | end 74 | 75 | formated_time 76 | end 77 | 78 | def self.format_cnpj(string) 79 | formated_cnpj = "" 80 | 81 | if not (string.empty? || string.size != 14) 82 | formated_cnpj = string[0,2] + '.' + string[2,3] + '.' + string[5,3] + 83 | '/' + string[8,4] + '-' + string[12,2] 84 | end 85 | 86 | formated_cnpj 87 | end 88 | 89 | private 90 | 91 | def self.extract_date_time(string) 92 | begin 93 | DateTime.strptime(string, "%Y-%m-%dT%H:%M:%S") 94 | rescue ArgumentError 95 | DateTime.strptime(string, "%d/%m/%Y %H:%M:%S") 96 | end 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /lib/ruby_danfe/options.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | class Options < OpenStruct 3 | 4 | DEFAULTOPTIONS = { 5 | quantity_decimals: 2, 6 | numerify_prod_qcom: false 7 | } 8 | 9 | def initialize(new_options={}) 10 | options = DEFAULTOPTIONS.merge(config_yaml_load) 11 | super options.merge(new_options) 12 | end 13 | 14 | private 15 | def file 16 | File.exist?("config/ruby_danfe.yml") ? File.open("config/ruby_danfe.yml").read : "" 17 | end 18 | 19 | def config_yaml_load 20 | @file_read = YAML.load(file) 21 | @file_read ? (@file_read["ruby_danfe"]||{})["options"] : {} 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ruby_danfe/railtie.rb: -------------------------------------------------------------------------------- 1 | require "prawn" 2 | require "prawn/table" 3 | require "prawn/measurement_extensions" 4 | require "barby" 5 | require "barby/barcode/code_128" 6 | require 'barby/barcode/qr_code' 7 | require "barby/outputter/prawn_outputter" 8 | require "nokogiri" 9 | require 'ostruct' 10 | require 'yaml' 11 | require 'date' 12 | require 'time' 13 | require 'json' 14 | 15 | require_relative '../ruby_danfe.rb' 16 | require_relative 'options.rb' 17 | require_relative 'helper.rb' 18 | require_relative 'cst.rb' 19 | require_relative 'document.rb' 20 | require_relative 'version.rb' 21 | require_relative 'dacte_generator.rb' 22 | require_relative 'dacteos_generator.rb' 23 | require_relative 'danfe_generator.rb' 24 | require_relative 'danfse_generator.rb' 25 | require_relative 'danfe_nfce_generator.rb' 26 | require_relative 'xml.rb' 27 | require_relative 'descricao.rb' 28 | require_relative 'ruby_danfe.rb' 29 | -------------------------------------------------------------------------------- /lib/ruby_danfe/ruby_danfe.rb: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | module RubyDanfe 3 | def self.generate(pdf_filename, xml_filename, type = :danfe, new_options = {}) 4 | self.options = new_options if !new_options.empty? 5 | 6 | xml_string = File.new(xml_filename) 7 | render_file(pdf_filename, xml_string, type) 8 | end 9 | 10 | def self.render(xml_string, type = :danfe, new_options = {}) 11 | self.options = new_options if !new_options.empty? 12 | 13 | pdf = generatePDF(xml_string, type) 14 | pdf.render 15 | end 16 | 17 | def self.render_file(pdf_filename, xml_string, type = :danfe, new_options = {}) 18 | self.options = new_options if !new_options.empty? 19 | 20 | pdf = generatePDF(xml_string, type) 21 | pdf.render_file pdf_filename 22 | end 23 | 24 | def self.options 25 | @options ||= RubyDanfe::Options.new 26 | end 27 | 28 | def self.options=(new_options = {}) 29 | @options = RubyDanfe::Options.new(new_options) 30 | end 31 | 32 | private 33 | def self.generatePDF(xml_string, type = :danfe, new_options = {}) 34 | self.options = new_options if !new_options.empty? 35 | 36 | xml = XML.new(xml_string) 37 | 38 | generator = 39 | case type 40 | when :danfe then DanfeGenerator.new(xml) 41 | when :danfe_nfce then DanfeNfceGenerator.new(xml) 42 | when :dacte then DacteGenerator.new(xml) 43 | when :danfse then DanfseGenerator.new(xml) 44 | when :dacteos then DacteosGenerator.new(xml) 45 | else raise "unknown type #{type}" 46 | end 47 | generator.generatePDF 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/ruby_danfe/version.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | VERSION = "1.15.4" 3 | end 4 | -------------------------------------------------------------------------------- /lib/ruby_danfe/xml.rb: -------------------------------------------------------------------------------- 1 | module RubyDanfe 2 | class XML 3 | def css(xpath) 4 | @xml.css(xpath) 5 | end 6 | 7 | def xpath(regex) 8 | doc = Nokogiri::HTML(@xml.to_s) 9 | return doc.xpath(regex) 10 | end 11 | 12 | def regex_string(search_string, regex) 13 | doc = Nokogiri::HTML(search_string) 14 | return doc.xpath(regex) 15 | end 16 | 17 | def initialize(xml) 18 | @xml = Nokogiri::XML(xml) 19 | end 20 | 21 | def [](xpath) 22 | node = @xml.css(xpath) 23 | return node ? node.text : "" 24 | end 25 | 26 | def render 27 | if @xml.at_css('infNFe/ide') 28 | RubyDanfe.render @xml.to_s, :danfe 29 | elsif @xml.at_css('InfNfse/Numero') 30 | RubyDanfe.render @xml.to_s, :danfse 31 | else 32 | if @xml.at_css('CTeOS') 33 | RubyDanfe.render @xml.to_s, :dacteos 34 | else 35 | RubyDanfe.render @xml.to_s, :dacte 36 | end 37 | end 38 | end 39 | 40 | def collect(ns, tag, &block) 41 | result = [] 42 | # Tenta primeiro com uso de namespace 43 | begin 44 | @xml.xpath("//#{ns}:#{tag}").each do |det| 45 | result << yield(det) 46 | end 47 | rescue 48 | # Caso dê erro, tenta sem 49 | @xml.xpath("//#{tag}").each do |det| 50 | result << yield(det) 51 | end 52 | end 53 | result 54 | end 55 | 56 | def inject(ns, tag, acc, &block) 57 | # Tenta primeiro com uso de namespace 58 | begin 59 | @xml.xpath("//#{ns}:#{tag}").each do |det| 60 | acc = yield(acc, det) 61 | end 62 | rescue 63 | # Caso dê erro, tenta sem 64 | @xml.xpath("//#{tag}").each do |det| 65 | acc = yield(acc, det) 66 | end 67 | end 68 | acc 69 | end 70 | 71 | def attrib(node, attrib) 72 | begin 73 | return @xml.css(node).attr(attrib).text 74 | rescue 75 | "" 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /ruby_danfe.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "ruby_danfe/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "ruby_danfe" 7 | spec.version = RubyDanfe::VERSION 8 | spec.summary = "DANFE and DACTE pdf generator for Brazilian invoices and transportation docs." 9 | spec.author = "Eduardo Reboucas" 10 | spec.email = "eduardo.reboucas@gmail.com" 11 | spec.homepage = "http://github.com/mcfox/ruby_danfe" 12 | spec.license = "MIT" 13 | 14 | spec.files = `git ls-files`.split("\n") 15 | spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 16 | spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 17 | spec.require_paths = ["lib"] 18 | 19 | 20 | spec.add_dependency "nokogiri", "> 1.8.5" 21 | spec.add_dependency "prawn", "~> 1.2" 22 | spec.add_dependency "prawn-table", "> 0.2" 23 | spec.add_dependency "barby", "> 0.5" 24 | spec.add_dependency "rqrcode", "> 0.10" 25 | spec.add_dependency "rake" 26 | 27 | spec.add_development_dependency "pry" 28 | spec.add_development_dependency "rspec", "> 3.0" 29 | spec.add_development_dependency "simplecov" 30 | end 31 | -------------------------------------------------------------------------------- /spec/features/ruby_danfe_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe "RubyDanfe generated pdf files" do 4 | let(:base_dir) { "./spec/fixtures/"} 5 | let(:output_pdf) { "#{base_dir}output.pdf" } 6 | 7 | before { 8 | File.delete(output_pdf) if File.exist?(output_pdf) 9 | RubyDanfe.options = {"quantity_decimals" => 2} 10 | } 11 | 12 | it "renders a basic NF-e with namespace" do 13 | expect(File.exist?(output_pdf)).to be_falsey 14 | 15 | RubyDanfe.generate(output_pdf, "#{base_dir}nfe_with_ns.xml") 16 | 17 | expect("#{base_dir}nfe_with_ns.xml.fixture.pdf").to be_same_file_as(output_pdf) 18 | end 19 | 20 | it "renders another basic NF-e without namespace" do 21 | expect(File.exist?(output_pdf)).to be_falsey 22 | 23 | RubyDanfe.generate(output_pdf, "#{base_dir}nfe_without_ns.xml") 24 | 25 | expect("#{base_dir}nfe_without_ns.xml.fixture.pdf").to be_same_file_as(output_pdf) 26 | end 27 | 28 | it "renders a NF-e having FCI in its items" do 29 | expect(File.exist?(output_pdf)).to be_falsey 30 | 31 | RubyDanfe.generate(output_pdf, "#{base_dir}nfe_with_fci.xml") 32 | 33 | expect("#{base_dir}nfe_with_fci.xml.fixture.pdf").to be_same_file_as(output_pdf) 34 | end 35 | 36 | it "renders a NF-e of Simples Nacional using CSOSN" do 37 | expect(File.exist?(output_pdf)).to be_falsey 38 | 39 | RubyDanfe.generate(output_pdf, "#{base_dir}nfe_simples_nacional.xml") 40 | 41 | expect("#{base_dir}nfe_simples_nacional.xml.fixture.pdf").to be_same_file_as(output_pdf) 42 | end 43 | 44 | it "renders a basic CT-e" do 45 | expect(File.exist?(output_pdf)).to be_falsey 46 | 47 | RubyDanfe.generate(output_pdf, "#{base_dir}cte.xml", :dacte) 48 | 49 | expect("#{base_dir}cte.xml.fixture.pdf").to be_same_file_as(output_pdf) 50 | end 51 | 52 | it "renders a basic NFS-e" do 53 | RubyDanfe.generate(output_pdf, "#{base_dir}nfse.xml", :danfse) 54 | 55 | expect("#{base_dir}nfse.xml.fixture.pdf").to be_same_file_as(output_pdf) 56 | end 57 | 58 | it "renders quantity field with 4 decimals" do 59 | expect(File.exist?(output_pdf)).to be_falsey 60 | 61 | RubyDanfe.generate(output_pdf, "#{base_dir}4_decimals_nfe_simples_nacional.xml", :danfe, {"quantity_decimals" => 4}) 62 | 63 | expect("#{base_dir}4_decimals_nfe_simples_nacional.xml.fixture.pdf").to be_same_file_as(output_pdf) 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/fixtures/4_decimals_nfe_simples_nacional.xml: -------------------------------------------------------------------------------- 1 | 35000000016101-Venda de producao do estabelecimento155112013-12-2813550308116110160891033000109KRON INSTRUMENTOS ELETRICOS LTDAKRON INSTRUMENTOS ELETRICOS LTDARUA ALEXANDRE DE GUSMAO278SOCORRO3550308SAO PAULOSP047600201058BRASIL1155252000111393871117182743287000880Schneider Electric Brasil LtdaAv da Saudade1125Frutal3552403SUMARESP131713201058BRASIL19210463006710083751101Tijolo Macico Tipo A69041000006101MI2.000010.000000000020.00MI2.000010.000000000015.350102990.000.000.00990.000.000.002Tijolo Macico Tipo B69041000006101MI3.000020.000000000060.00MI3.000020.0000000000116.050102990.000.000.00990.000.000.003Tijolo Macico Tipo C69041000006101MI4.000030.0000000000120.00MI4.000030.0000000000132.100102990.000.000.00990.000.000.000.000.000.000.00200.000.000.000.000.000.000.000.000.00200.0053.500112014-01-2740.0022014-02-2640.0032014-03-2840.0042014-04-2740.0052014-05-2740.00DOCUMENTO EMITIDO POR ME OU EPP OPTANTE PELO SIMPLES NACIONAL * NAO GERA DIREITO A CREDITO FISCAL DE IPI * Tributos: R$ 53,50 (26,75%) 2 | -------------------------------------------------------------------------------- /spec/fixtures/cte.xml: -------------------------------------------------------------------------------- 1 | 420060002256352PRESTACAO SERVICO TRANSP A ESTAB INDUSTRIAL15702252011-07-26T17:34:0011010010.054202404BLUMENAUSC0114213203POMERODESC4313904PANAMBIRS13REMESSA 011862043889317697001880251944646TRANSPORTES WALDEMAR LTDAR HEINRICH HEMMER3047BADENFURT4202404BLUMENAU89070000SCBRASIL62800446001634253821827NALCO BRASIL LTDARUA ALBERTO SPREDEMANN329FUNDOSCENTRO4213203POMERODE89107000SCBRASIL42110762800446001634550010000044551217916180896731640001930900018909BRUNING TECNOMETAL S ARUA VINTE E CINCO DE JULHO2305JACIANDI4313904PANAMBI98280000RSBRASIL146.39146.39FretePeso72.40GRIS3.61SEC/CAT48.27TaxaPedagio5.23ValorLiquido146.39AdValorem16.8800146.3912.0017.572120.80LIQUIDO CORROSIVO ACIDO INORGANICO03VOLUME4.0000080822000234502011-07-290VAHbZ77V2XkfJ/a9HkjUEZU17rw=GpFAhaFZViTVUIdYvgpGm8wIsytVOMjmvEGEb2fVIhryXEnj3kYGUmiWgPGRprUwV/C2bkdFaoioS//v4VEd95xjKD0MuV+uZhih6Q7sLSlkxH3wD2w49VDM9wJVxO9Pp0I4VU28FVbT44QKGjhDSYn+3EqJN1k+VJEhem69lik=MIIGWjCCBUKgAwIBAgIIfE0nfEKvLwowDQYJKoZIhvcNAQEFBQAwdTELMAkGA1UEBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEgZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEZMBcGA1UEAxMQQUMgU0VSQVNBIFJGQiB2MTAeFw0xMTA3MDYxMTU3MzVaFw0xMjA3MDUxMTU3MzVaMIHaMQswCQYDVQQGEwJCUjELMAkGA1UECBMCUlMxEjAQBgNVBAcTCUNBUkFaSU5ITzETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRYwFAYDVQQLEw1SRkIgZS1DTlBKIEExMRIwEAYDVQQLEwlBUiBTRVJBU0ExMTAvBgNVBAMTKFRSQU5TUE9SVEVTIFdBTERFTUFSIExUREE6ODkzMTc2OTcwMDAxMzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBVCMXNB+b8uHoxu3Wn0Jm6xGjg+v2KRx6IHShapVRdGXxNaPqu6oZ8JRqA18i9+/3J57dvg7BqccMggwhe8179V8nyLeMSbnoGrKQDhzRvZLDM83DQBPtAwdVrDBVoNsfz+/uWjkJ2ooFBCt5EzA1mamPjPNQTggTjGODEoEshAgMBAAGjggMKMIIDBjAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwHwYDVR0jBBgwFoAUmt0itvZ36UJvSMJRQKBW4vN0P7swgb0GA1UdEQSBtTCBsoEiQ09OVEFCSUxJREFERUBUV1RSQU5TUE9SVEVTLkNPTS5CUqAZBgVgTAEDAqAQEw5WQUxERU1BUiBLTEVJTqAZBgVgTAEDA6AQEw44OTMxNzY5NzAwMDEzMqA9BgVgTAEDBKA0EzIxMzA1MTk0MTE4MTIzMTM5MDA0MDAwMDAwMDAwMDAwMDAwMDEwMTY4MjM3NjVTU1BSU6AXBgVgTAEDB6AOEwwwMDAwMDAwMDAwMDAwVwYDVR0gBFAwTjBMBgZgTAECAQ0wQjBABggrBgEFBQcCARY0aHR0cDovL3d3dy5jZXJ0aWZpY2Fkb2RpZ2l0YWwuY29tLmJyL3JlcG9zaXRvcmlvL2RwYzCB8wYDVR0fBIHrMIHoMEqgSKBGhkRodHRwOi8vd3d3LmNlcnRpZmljYWRvZGlnaXRhbC5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL3NlcmFzYXJmYnYxLmNybDBEoEKgQIY+aHR0cDovL2xjci5jZXJ0aWZpY2Fkb3MuY29tLmJyL3JlcG9zaXRvcmlvL2xjci9zZXJhc2FyZmJ2MS5jcmwwVKBSoFCGTmh0dHA6Ly9yZXBvc2l0b3Jpby5pY3BicmFzaWwuZ292LmJyL2xjci9TZXJhc2EvcmVwb3NpdG9yaW8vbGNyL3NlcmFzYXJmYnYxLmNybDCBmQYIKwYBBQUHAQEEgYwwgYkwSAYIKwYBBQUHMAKGPGh0dHA6Ly93d3cuY2VydGlmaWNhZG9kaWdpdGFsLmNvbS5ici9jYWRlaWFzL3NlcmFzYXJmYnYxLnA3YjA9BggrBgEFBQcwAYYxaHR0cDovL29jc3AuY2VydGlmaWNhZG9kaWdpdGFsLmNvbS5ici9zZXJhc2FyZmJ2MTANBgkqhkiG9w0BAQUFAAOCAQEAgVHQIzWgqmBMT+0fsh9bpJE45ZTfT+qVQMUtlDN5XNRkOU5mm7xB98svNuVxw7cxehC0CzOte0C3b+slLRdGHkH2ay5awi3FKnhq0O0wPZynzspy6Ily/EqVHaAwFs/Rm1mcisMj0i0ETAy15Cczq1kZGbWsIAVuWTtqvgItZ7Keg1/Pa3m6TdDHm5XcunUFybTSmfL+sDsrIjb3BZZZPxSWTkFg90iPKE3hyy2t9YCtq8Dxu3UIMARHx572LWGDNG4CWmg3SJVUEzF9BB+XS9wGUTE+OH0aM83D7Z3fK8wyoxRhPmEetCeUijjDzih0CJh3u+gufrhpL9/hS1wJDQ==1RS20100930124337421107893176970018805700000000022500600022502011-07-26T17:58:01342110001068545VAHbZ77V2XkfJ/a9HkjUEZU17rw=100Autorizado o uso do CT-e -------------------------------------------------------------------------------- /spec/fixtures/nfe_date_format_infoadprod_infoadfisco_issues.xml: -------------------------------------------------------------------------------- 1 | 3580000042RETORNO/INDUSTRIALIZAÇÃO EFETUADA PARA OUTRO ESTABELECIMENTO155120952014-03-12135231071101132.2.2159374918000143TECNOLIGAS INDÚSTRIA E COMÉRCIO DE METAIS LTDATECNOLIGASRUA COBALTO19CORREDOR INDUSTRIAL3523107ItaquaquecetubaSP085861201058BRASIL0114648664437902942011062962452100145581238000196DAISA INDUSTRIA METALURGICA LTDAAV HELIO OSSAMU DAIKUARA1800 BVISTA ALEGRE3515004EmbuSP068070001058BRASIL114704552229800652911702RECUPERACAO DE BORRA DE ALUMINIO (TRANSFORMACAO PARA LINGOTES)760200005124KG3323.00001.25000000004153.75KG3323.00001.2500000000101012.84117.9607699951024153.750.2811.63024153.751.1648.1814RETORNO DE MERCADORIA RECEBIDA PARA TRANSFORMACAO PARA LINGOTES DE ALUMINIO760200005902KG5200.00003.000000000015600.00KG5200.00003.000000000010400076999530808MATERIAL DE VOSSA PROPR. CF NF Nº 026.039 DE 07/03/2014, QUE RETORNAM TRANSFORMADOS EM LINGOTES DE ALUMINIO COM QUEBRA = 1.877 KG.0.000.000.000.0019753.750.000.000.000.000.0011.6348.180.0019753.75159374918000143TECNOLIGAS INDUSTRIA E COMERCIO DE METAIS LTDA379029420110RUA COBALTO, 19ItaquaquecetubaSPA GRANELS/MS/N5200.0005200.00020954153.754153.752095/12014-04-114153.75EMPRESA OPTANTE PELO SIMPLES NACIONAL.bAGJFpwJ1TznKGjrfj3nAV6+pIs=SPGXJgTe1J2XByj2l6MmvtXw9W1J0nAu8tf809v6r/appFbkEGeLcvbW26u53DGCSiWTt9oiUmUH 2 | hph/GNYVN1WVDK55UhpetP7xDd5qHsg0X/vyrUXBoT+IZ0O28FF/Ndwu+hCrB6xYwZCGQmGkRQ7G 3 | TZvMvMjvm74/jAE2XNNGZOc0qHPqn0DnIadMD6aYX4eo/Y9JXpPrSzrR1r47MlHfFPP2VsyoQ6+F 4 | 3XHhNW6yfVdxGbsxVvrgAaX41CgbU7mZZwG63Tx3M3COmwFYRuOpZBugvPGOVmgtooDETv9fcrFS 5 | Kyga49JFCoPuYoF3Ch1XnA3gusvc5Q9GZxSfdA==MIIIZDCCBkygAwIBAgIQHCgWAi5evL0ekPewJ3yeijANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQG 6 | EwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRh 7 | IEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYDVQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4X 8 | DTEyMDUxMTAwMDAwMFoXDTE1MDUxMDIzNTk1OVowggEMMQswCQYDVQQGEwJCUjETMBEGA1UEChQK 9 | SUNQLUJyYXNpbDELMAkGA1UECBMCU1AxGDAWBgNVBAcUD0lUQVFVQVFVRUNFVFVCQTE2MDQGA1UE 10 | CxQtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRYwFAYDVQQL 11 | FA1SRkIgZS1DTlBKIEEzMSYwJAYDVQQLFB1BdXRlbnRpY2FkbyBwb3IgQVIgR3VhcnVmb3J0ZTFJ 12 | MEcGA1UEAxNAVEVDTk9MSUdBUyBJTkRVU1RSSUEgRSBDT01FUkNJTyBERSBNRVRBSVMgTFREQSBF 13 | UDo1OTM3NDkxODAwMDE0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmyIeuvBdoj 14 | hMC73wPtiu59bW/u2DplnOv1pl9OkyHrd1+k6uHwsLXjDcf54mEJ9fJtZXvp4iVkHiJ1pCw4BEzx 15 | +PhBdzvix5wMGztlcqk2aN7dQtqr/8L7b6ARDpGIRVZoHUCC+6PwxtIYgA/DSFfAe1fqHBQr4vkD 16 | rEcJGZ/EsyZASsUgkdOkzO9/XlUaCGds1nQ3R1kiSeakglgRG6QMwKIYlgV/N/DYhS/F0Yioa1Go 17 | 16zpo7OaOh1LBgxtLaEbtqWcE3Sd7GMcnSI2qnFshSjOKVj0RNQgFgZVSDofqjvLscLBxkS820qH 18 | O+Mj2Sn8DCY387i4ngxIcydq4gkCAwEAAaOCA1IwggNOMIG3BgNVHREEga8wgaygOAYFYEwBAwSg 19 | LwQtMTUxMDE5NjIwMTI4ODU5MDgzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwoCMGBWBMAQMC 20 | oBoEGEFHTkFMRE8gQk9ORVRURSBQT0xJRE9SSaAZBgVgTAEDA6AQBA41OTM3NDkxODAwMDE0M6AX 21 | BgVgTAEDB6AOBAwwMDAwMDAwMDAwMDCBF3RlY25vbGlnYXNAdGVycmEuY29tLmJyMAkGA1UdEwQC 22 | MAAwHwYDVR0jBBgwFoAULpHq1m3lslmC3DiFKXY0FlY80D4wDgYDVR0PAQH/BAQDAgXgMH8GA1Ud 23 | IAR4MHYwdAYGYEwBAgMGMGowaAYIKwYBBQUHAgEWXGh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2ln 24 | bi5jb20uYnIvcmVwb3NpdG9yaW8vZHBjL0FDX0NlcnRpc2lnbl9SRkIvRFBDX0FDX0NlcnRpc2ln 25 | bl9SRkIucGRmMIIBFgYDVR0fBIIBDTCCAQkwV6BVoFOGUWh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRp 26 | c2lnbi5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0ZXN0Q1JMLmNy 27 | bDBWoFSgUoZQaHR0cDovL2ljcC1icmFzaWwub3V0cmFsY3IuY29tLmJyL3JlcG9zaXRvcmlvL2xj 28 | ci9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5jcmwwVqBUoFKGUGh0dHA6Ly9yZXBvc2l0b3Jp 29 | by5pY3BicmFzaWwuZ292LmJyL2xjci9DZXJ0aXNpZ24vQUNDZXJ0aXNpZ25SRkJHNC9MYXRlc3RD 30 | UkwuY3JsMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDCBmwYIKwYBBQUHAQEEgY4wgYsw 31 | XwYIKwYBBQUHMAKGU2h0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2lnbi5jb20uYnIvcmVwb3NpdG9y 32 | aW8vY2VydGlmaWNhZG9zL0FDX0NlcnRpc2lnbl9SRkJfRzQucDdjMCgGCCsGAQUFBzABhhxodHRw 33 | Oi8vb2NzcC5jZXJ0aXNpZ24uY29tLmJyMA0GCSqGSIb3DQEBCwUAA4ICAQDPdVSjPZ7tdTx4pCHV 34 | OOmbEJ5PP5RkTvZ1FCspjJ5jNSNqrGAp/dm19OeTg0rBeqZ+SJgA6TuinpgtGL+vwtMquDGeLLef 35 | n7Df/OKtrLJkfK+vfTpK6MuJBahmI8nyHv5ouoSBEpJ8byDo1a+OSgXAaYsBasC0I3shpdLdzZ1h 36 | k35x6kUlEirQyHMtbxlOAw+HfzQmv+1qOZpt3ElbC1CtR1Bun56JC5YuiOAd03OhJP01JAnzw5Ze 37 | XnAfmEQh35310+PLTnJAD8mdPNMXdZAXBhIspyDMy/gM2ou5R/9k5coK2fTcwjqH0atL9ezGnBqB 38 | vH9txy8ArcdWrosjLuNrbOq4fqrK8PjUZKVptBYMh4nEMwf8uI2ega1E+0TEwIFx7TnVvUR3U3DO 39 | u2Zl/U+9Pc16LBRAubafO68PnGn9IeEgLE5dL1mkG34lHxhU4oLF7q631divGR4B5DIA/UjhiRnJ 40 | nsGL+STa2q3i5sOMfuhhhr3UIVg/xkbeFZHx+NK/1BJe1/eDmiK4eofAYVCzhb1yRHWotDJMQ6yq 41 | dVvIdpia77H57h02bwtd0YoQ8yC8daVH0roZONE2klI55XrThX7GV372Vm/K03anTZS9KKDpzXMu 42 | THTsT17MV8IxuMX21LRkitKSO4Y6l+C6Y09bT/MX/rQSBNopxtLgBPu8iQ==1SP_NFE_PL_006q351403593749180001435500100000209518000004202014-03-12T10:41:31135140152647164bAGJFpwJ1TznKGjrfj3nAV6+pIs=100Autorizado o uso da NF-e -------------------------------------------------------------------------------- /spec/fixtures/nfe_simples_nacional.xml: -------------------------------------------------------------------------------- 1 | 35000000016101-Venda de producao do estabelecimento155112013-12-2813550308116110160891033000109KRON INSTRUMENTOS ELETRICOS LTDAKRON INSTRUMENTOS ELETRICOS LTDARUA ALEXANDRE DE GUSMAO278SOCORRO3550308SAO PAULOSP047600201058BRASIL1155252000111393871117182743287000880Schneider Electric Brasil LtdaAv da Saudade1125Frutal3552403SUMARESP131713201058BRASIL19210463006710083751101Tijolo Macico Tipo A69041000006101MI2.000010.000000000020.00MI2.000010.000000000015.350102990.000.000.00990.000.000.002Tijolo Macico Tipo B69041000006101MI3.000020.000000000060.00MI3.000020.0000000000116.050102990.000.000.00990.000.000.003Tijolo Macico Tipo C69041000006101MI4.000030.0000000000120.00MI4.000030.0000000000132.100102990.000.000.00990.000.000.000.000.000.000.00200.000.000.000.000.000.000.000.000.00200.0053.500112014-01-2740.0022014-02-2640.0032014-03-2840.0042014-04-2740.0052014-05-2740.00DOCUMENTO EMITIDO POR ME OU EPP OPTANTE PELO SIMPLES NACIONAL * NAO GERA DIREITO A CREDITO FISCAL DE IPI * Tributos: R$ 53,50 (26,75%) 2 | -------------------------------------------------------------------------------- /spec/fixtures/nfe_with_fci.xml: -------------------------------------------------------------------------------- 1 | 3563472050VENDA DE PRODUCAO DO ESTABELECIMENTO1551445252013-10-18135503081151105.060891033000109KRON INSTRUMENTOS ELETRICOS LTDAKRONRUA ALEXANDRE DE GUSMAO278SOCORRO3550308SAO PAULOSP047600201058BRASIL1155252000111393871117382743287000880SCHNEIDER ELECTRIC BRASIL LTDAAV. DA SAUDADE1125FRUTAL3552403SUMARESP131713201058BRASIL1921046300671008375110nfemerc.sumare@br.schneider-electric.comF211130101000AMPERIMETRO FM72PC 300/5A COD 3491192843 RL90303329005101PC1.0049.2349.23PC1.0049.231980019211012232531-74B2-4FDD-87A6-CF0AD3E55386500349.2312.005.909995049.235.002.460149.230.650.320149.233.001.4849.235.900.000.0049.230.000.000.000.002.460.321.480.0051.69050547058000128POST MASTER COMERCIAL LTDA111768652113RUA VIEIRA DE MORAES 558SAO PAULOSP1CAIXAKRON11.0001.0000044525/012013-12-1751.69FRETE CIF / INDUSTRIALIZACAO PEDIDO 98001921 VENC. DAS DUPLICATAS 01/ 10 / 20 DO MES - VIA DEPOSITO [EMAIL=nfemerc.sumare@br.schneider-electric.com]98001921dndW1koiOiYKZkXf7cWtg5vfL2Y=JXN6WtG/sLQgtEI0n0BhajaphVDAX99A+QcrC3XxTkP4vZ/yHpwr2ngvs3t0M1uLECymakCxjT/qMmanJDiaAGxfWmBJkdgDFa80zJ2RoS9RqF48QmNXHfDNtjwwgw12RlFC8reLWGw7qXD9Nre5E9bTWJqEH4RHhKcg/akiWsQ2uy6M2O/m3IgznCG6wMnhaE98BbXTqcHLrvRignT86HQssaV6DDVm2kXyL1FM8YMZF3TtbsMQ8PJs70FrwddVzFIPoYxSq7iBw40ZdveuexYApVYJdyUssBZcxnlWtaS9aOWpd1fqHiQy5fKRRycBwOdMEPcQXGKqkNUs1hlUtg==MIIIQjCCBiqgAwIBAgIQdHnQdADNdDiHWqCYm1mh6zANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYDVQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4XDTEzMDIyNTAwMDAwMFoXDTE0MDIyNDIzNTk1OVowgfExCzAJBgNVBAYTAkJSMRMwEQYDVQQKFApJQ1AtQnJhc2lsMQswCQYDVQQIEwJTUDESMBAGA1UEBxQJU0FPIFBBVUxPMTYwNAYDVQQLFC1TZWNyZXRhcmlhIGRhIFJlY2VpdGEgRmVkZXJhbCBkbyBCcmFzaWwgLSBSRkIxFjAUBgNVBAsUDVJGQiBlLUNOUEogQTExIjAgBgNVBAsUGUF1dGVudGljYWRvIHBvciBBUiBGQUNFU1AxODA2BgNVBAMTL0tST04gSU5TVFJVTUVOVE9TIEVMRVRSSUNPUyBMVERBOjYwODkxMDMzMDAwMTA5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs7JenW0yMGg/bzp+ByFBjxG2nxE9DvzegNzr9NzH+ob+9nCm2iCDaB12dytrPD9aJYXE9Y4AcO+R8a5iUkTaGS4fGAfT11JSNyFLmatR+Z5AJZZ4j0N6g5moRWxOShPjoqxPf43IpAFwQrb2AhWi+wrTtwbS89jvVonGQvEdQsS1zkzX7KWvvy2bFcUCupvXd+TP0aIdyi2XjCkpGT0j3T1qvZrz2WnbhWW4VqZVfXiVZyYhijgbi+IO7s5wrYVTJCZtNvoffRsmGh+aTTlGgapjatWN+3u+M885Y4umFBqEmGgWxoidO1xXiURYhkLF5w2wlxJlwcC0qsF2wpuPOwIDAQABo4IDTDCCA0gwgbEGA1UdEQSBqTCBpqA4BgVgTAEDBKAvBC0yOTA3MTk1NTAxMjU1MzE4ODU2MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCgJQYFYEwBAwKgHAQaRkVSTkFORE8gTUFSQ0hFVFRJIEJFRElDS1OgGQYFYEwBAwOgEAQONjA4OTEwMzMwMDAxMDmgFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwgQ9jcGRAa3Jvbi5jb20uYnIwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBQukerWbeWyWYLcOIUpdjQWVjzQPjAOBgNVHQ8BAf8EBAMCBeAwfwYDVR0gBHgwdjB0BgZgTAECAQwwajBoBggrBgEFBQcCARZcaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9kcGMvQUNfQ2VydGlzaWduX1JGQi9EUENfQUNfQ2VydGlzaWduX1JGQi5wZGYwggEWBgNVHR8EggENMIIBCTBXoFWgU4ZRaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9sY3IvQUNDZXJ0aXNpZ25SRkJHNC9MYXRlc3RDUkwuY3JsMFagVKBShlBodHRwOi8vaWNwLWJyYXNpbC5vdXRyYWxjci5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0ZXN0Q1JMLmNybDBWoFSgUoZQaHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5nb3YuYnIvbGNyL0NlcnRpc2lnbi9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5jcmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGbBggrBgEFBQcBAQSBjjCBizBfBggrBgEFBQcwAoZTaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9jZXJ0aWZpY2Fkb3MvQUNfQ2VydGlzaWduX1JGQl9HNC5wN2MwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmNlcnRpc2lnbi5jb20uYnIwDQYJKoZIhvcNAQELBQADggIBAK22zXyUD+FxXBLcP99DfElExHg7a8ZIqCNQs58pG5xR5rNYib46z6tGmEsWCbgViagokqdyQmLNAfE/t1UqOdu4dxMoQM2m5O3Nk/PDOaVVe5y93dFBOr5xMQsfQFtcHbWO0QTeJdG0Uh0LxhRVriPH9JmvAMPUjUl9W/+/hIjohh/zVDyX8WfBKRvVqn/RbFaBSyoYiLDBQWZ4FecrcqX/IXViSDM4d6jFS7+6OSFHgxzl08M4zAqaaSD51IQ3N9fcdhTolVAgHSNNMou88eJaRhbMGtX5qciiUbDTgaX69VbPWeSKtA3TpHKMvNidZTfhhu8X/MxqztTpEEUrKfxRLkIUdVkho3a2/GfD3ePcy7k+Zexu2u1vTkXSGXKDvrJkowOXI11Xob6CP6ZNCCaftdQ+8WA+kZpthjILhY6G7jYy20OFiPTPLwC70funz+wkAB2upX7fMkxctTuAEEbecwcshJS4IgOJCOWPjuOFVMrCOKi1xgPZTxmmHZ9JcVik2Z7JlwV2r+j2sjAYYCFExipw2PmbTDtSL3worhASMsllWYaSmGM524aPEWXiemR0zfKEUuS5wDBdFJrsZkjJDIFJs0AmP2rXf2ftoN73g/ap2ycqbgpt5NYBhhN1az9sc/n6062WatrXVrj94Vx8j+8j6L42Qwx+PrB9Fzrr1SP_NFE_PL_006q351310608910330001095500100004452516347205052013-10-18T13:54:04135130636167763dndW1koiOiYKZkXf7cWtg5vfL2Y=100Autorizado o uso da NF-e -------------------------------------------------------------------------------- /spec/fixtures/nfe_with_ns.xml: -------------------------------------------------------------------------------- 1 | 2500013415Vendas de producao do estabelecimento1552134152011-10-292011-10-2912507507111110Integrat12345678901234ACME SAACME-PBRUA HORTENCIO RIBEIRO DE LUNA3333DISTRITO INDUSTRIAL2507507Joao PessoaPB580814001058BRASIL8321062200160158257398765432101234EDITORA BLEBLEBLE LTDARUA URBANO SANTOS, N755 (ANT 160)0CUMBICA3518800GuarulhosSP071823201058BRASIL1127901347336322171116 2 | 00005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.00 3 | 00005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.0000005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.00 4 | 0.000.000.000.00110635.200.000.000.000.000.000.000.000.00110635.20010849477000108TRANSPRINT - TRANSPORTADORA E LOGISTICA LTDA148613972111Rua do TatuapeSAO PAULOSP00000000SP00000026VOLUMES(s)DIVERSOS025000.00025000.00013415//1110635.20110635.2013415//1-12012-02-26110635.20Obs: PEDIDO DE COMPRA: 308.996 MATERIAL IMUNE CONFORME ART.150 INCISO VI ALINEA D DA CONSTITUICAO FEDERAL.9jeTTSaza8lMT2Xk5hbWx86Fbp4=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1SVRS20110801092042251110123456789012345500200001341510001341512011-10-29T14:37:093251100128663209jeTTSaza8lMT2Xk5hbWx86Fbp4=100Autorizado o uso da NF-e 5 | -------------------------------------------------------------------------------- /spec/fixtures/nfe_without_ns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3191136050REMESSA MERC. P/ CONSERTO055100121182013-02-22131186011171105.099984626000136ACME SAACMEVIA EXPRESSA DE CONTAGEM3850CINCAO3118601CONTAGEMMG323704851058BRASIL31339966001862422430000398765432101234BLABLABLA LTDAAV. MARGINAL DO RIB. DOS CRISTAIS200JORDANESIA3509205CAJAMARSP077600001058BRASIL3130698013241029868119F-MERCPCMONITOR DE ARCO ELETRICO COD:1-VAMP2213A3AAA NS: V221-00663085369090006915pc1.004491.254491.25pc1.004491.25109030.000.000.0040.000.000.00999510707F-MERCPCDETECTOR FALHA ISOLAMENTO COD:1-XD312127-01 NS: 1518385V185369090006915pc1.001588.701588.70pc1.001588.70109030.000.000.0040.000.000.00999510707F-MERCPCMONITOR DE ARCO ELETRICO COD:1-VAMP2213A3AAA NS: V221-00682485369090006915pc1.004038.754038.75pc1.004038.75109030.000.000.0040.000.000.009995107070.000.000.000.0010118.700.000.000.000.000.000.000.000.0010118.70020147617000141JAMEF TRANSPORTADORA LTDA0624426220024RUA DR JOSE AMERICO CANCADO BAHIA 1810CONTAGEMMG2.10.00010.000MATERIAL DE NOSSA PROPRIEDADE QUE SEGUE PARA REPAROS, DEVENDO RETORNAR AO NOSSO ESTABELECIMENTO. **** ICMS SUSPENSO CONF.ART.19 ITEM 1 ANEXO III DEC.43080 IPI SUSPENSO CONF.ART.42 INCISO XIII DEC.4544 DEZ/02 ROMA-491 | Cod.Repart.Fiscal: 00001CAmkmMtOyPC1hfWU/LLGQUdAZ6Q=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113_0_61311302123456789012345510000001211819113605072013-02-22T09:32:54131131006404486CAmkmMtOyPC1hfWU/LLGQUdAZ6Q=100Autorizado o uso da NF-e -------------------------------------------------------------------------------- /spec/fixtures/nfse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 56293 7 | VKLN-H5PH 8 | 2018-09-03T11:30:07 9 | 10 | 59566 11 | A 12 | 1 13 | 14 | 2018-09-03 15 | 1 16 | 2 17 | 2 18 | 2018-09-03T00:00:00 19 | 20 | 21 | 2464 22 | 22.17 23 | 2 24 | 49.28 25 | 2464 26 | 0.02 27 | 2441.83 28 | 29 | 1602 30 | 160202 31 | Serviços prestados por condutores autônomos de táxi......:2.464,00 32 | Dispensa da retencao da CSLL conforme o art. 39 da Lei 10.865/2004. 33 | Servico nao sujeito a retencao de PIS e COFINS conforme Lei 10.833/2003 34 | combinada com o IN nr 381/2003 e nao contida no RIR /99 Art 647 35 | Conforme lei 12.649/2012 as cooperativas ficam isentas do PIS e da COFINS sobre os valores devidos aos 36 | cooperados 37 | BASE IRRF.........: 2.464,00 38 | PARTE TRIBUTAVEL..: 1.478,40 39 | VALOR IRRF........: 22,17 40 | CODIGO DO CLIENTE.: [ 004219 ] VENCIMENTO..: 24/09/2018 41 | PROCON-RJ - TEL 151 - RUA DA AJUDA, 5 - CENTRO - RIO DE JANEIRO - CEP - 20040-000 42 | CODECON ALERJ - TEL 0800 282 7060 - RUA DA ALFANDEGA, 8 - TERREO- CENTRO - RIO DE JANEIRO 43 | 44 | 3304557 45 | 46 | 47 | 48 | 30921357000173 49 | 982989 50 | 51 | COOPATAXI COOP DE CONS E TRAB DOS MOT AUT DE TAXI DO MUN DO RIO DE JANEIRO LTDA 52 | COOPATAXI 53 | 54 | RUA HERCULANO PENA 667 55 | 667 56 | CAVALCANTI 57 | 3304557 58 | RJ 59 | 21381410 60 | 61 | 62 | 32884343 63 | faturamento@coopataxi.com.br 64 | 65 | 66 | 67 | 68 | 69 | 03597703000137 70 | 71 | 2764032 72 | 73 | SITA INC DO BRASIL LTDA 74 | 75 | AVN RIO BRANCO 53, SAL 801 802 901 E 902 76 | 53 77 | SAL 801 802 901 E 902 78 | CENTRO 79 | 3304557 80 | RJ 81 | 20090004 82 | 83 | 84 | 2132637215 85 | invoices-brazil@sita.aero 86 | 87 | 88 | 89 | 3304557 90 | RJ 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /spec/lib/cst_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe RubyDanfe::Cst do 4 | let(:xml_cst) do 5 | xml = <<-eos 6 | 7 | 8 | 9 | 5 10 | 00 11 | 3 12 | 49.23 13 | 12.00 14 | 5.90 15 | 16 | 17 | 18 | eos 19 | 20 | Nokogiri::XML(xml) 21 | end 22 | 23 | let(:xml_csosn) do 24 | xml = <<-eos 25 | 26 | 27 | 28 | 4 29 | 102 30 | 31 | 32 | 33 | eos 34 | 35 | Nokogiri::XML(xml) 36 | end 37 | 38 | describe ".to_danfe" do 39 | context "when CST" do 40 | it "returns origin + CST" do 41 | expect(RubyDanfe::Cst.to_danfe(xml_cst)).to eq "500" 42 | end 43 | end 44 | 45 | context "when CSOSN" do 46 | it "returns origin + CSOSN" do 47 | expect(RubyDanfe::Cst.to_danfe(xml_csosn)).to eq "4102" 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/lib/descricao_spec.rb: -------------------------------------------------------------------------------- 1 | #encoding: utf-8 2 | 3 | require "spec_helper" 4 | 5 | describe RubyDanfe::Descricao do 6 | LINEBREAK = "\n" 7 | 8 | let(:xml_fci) do 9 | xml = <<-eos 10 | 11 | 12 | MONITOR DE ARCO ELETRICO 13 | 12232531-74B2-4FDD-87A6-CF0AD3E55386 14 | 15 | 16 | eos 17 | 18 | Nokogiri::XML(xml) 19 | end 20 | 21 | let(:xml_st) do 22 | xml = <<-eos 23 | 24 | 25 | MONITOR DE ARCO ELETRICO 26 | 27 | 28 | 96.73 29 | 30 | 31 | 56.00 32 | 479.82 33 | 17.00 34 | 29.28 35 | 36 | 37 | 38 | 39 | eos 40 | 41 | Nokogiri::XML(xml) 42 | end 43 | 44 | let(:xml_infAdProd) do 45 | xml = <<-eos 46 | 47 | 48 | MONITOR DE ARCO ELETRICO 49 | 50 | Informações adicionais do produto 51 | 52 | eos 53 | 54 | Nokogiri::XML(xml) 55 | end 56 | 57 | let(:xml_veicProd) do 58 | xml = <<-eos 59 | 60 | 61 | MOTOCICLETA 62 | 63 | 32A1SF354S6FASD213ASD5 64 | PRETA 65 | DSA5DA-321503 66 | 2018 67 | 2018 68 | 69 | 70 | 71 | eos 72 | 73 | Nokogiri::XML(xml) 74 | end 75 | 76 | let(:xml_IFC_ST_infAdProd) do 77 | xml = <<-eos 78 | 79 | 80 | MONITOR DE ARCO ELETRICO 81 | 12232531-74B2-4FDD-87A6-CF0AD3E55386 82 | 83 | 84 | 96.73 85 | 86 | 87 | 56.00 88 | 479.82 89 | 17.00 90 | 29.28 91 | 92 | 93 | 94 | Informações adicionais do produto 95 | 96 | eos 97 | 98 | Nokogiri::XML(xml) 99 | end 100 | 101 | describe ".generate" do 102 | context "when have FCI" do 103 | it "returns product + FCI" do 104 | string = "MONITOR DE ARCO ELETRICO" 105 | string += LINEBREAK 106 | string +="FCI: 12232531-74B2-4FDD-87A6-CF0AD3E55386" 107 | expect(RubyDanfe::Descricao.generate(xml_fci)).to eq string 108 | end 109 | end 110 | 111 | context "when have ST" do 112 | it "returns product + ST" do 113 | string = "MONITOR DE ARCO ELETRICO" 114 | string += LINEBREAK 115 | string += "ST: MVA: 56.00% " 116 | string += "* Alíq: 17.00% " 117 | string += "* BC: 479.82 " 118 | string += "* Vlr: 29.28" 119 | expect(RubyDanfe::Descricao.generate(xml_st)).to eq string 120 | end 121 | end 122 | 123 | context "when have infAdProd" do 124 | it "returns product + infAdProd" do 125 | string = "MONITOR DE ARCO ELETRICO" 126 | string += LINEBREAK 127 | string += "Informações adicionais do produto" 128 | expect(RubyDanfe::Descricao.generate(xml_infAdProd)).to eq string 129 | end 130 | end 131 | 132 | context "when have veicProd" do 133 | it "returns product + veicProd" do 134 | string = "MOTOCICLETA" 135 | string += LINEBREAK 136 | string += "Chassi: 32A1SF354S6FASD213ASD5 " 137 | string += "Motor: DSA5DA-321503 " 138 | string += "AnoFab: 2018 " 139 | string += "AnoMod: 2018 " 140 | string += "Cor: PRETA" 141 | expect(RubyDanfe::Descricao.generate(xml_veicProd)).to eq string 142 | end 143 | end 144 | 145 | context "when have FCI + ST + infAdProd" do 146 | it "returns product + FCI + ST + infAdProd" do 147 | string = "MONITOR DE ARCO ELETRICO" 148 | string += LINEBREAK 149 | string += "Informações adicionais do produto" 150 | string += LINEBREAK 151 | string +="FCI: 12232531-74B2-4FDD-87A6-CF0AD3E55386" 152 | string += LINEBREAK 153 | string += "ST: MVA: 56.00% " 154 | string += "* Alíq: 17.00% " 155 | string += "* BC: 479.82 " 156 | string += "* Vlr: 29.28" 157 | expect(RubyDanfe::Descricao.generate(xml_IFC_ST_infAdProd)).to eq string 158 | end 159 | end 160 | end 161 | end 162 | -------------------------------------------------------------------------------- /spec/lib/helper_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe RubyDanfe::Helper do 4 | describe ".format_datetime" do 5 | context "when date format is %Y-%m-%d" do 6 | it "returns a formated string" do 7 | string = "2013-10-18T13:54:04" 8 | expect(RubyDanfe::Helper.format_datetime(string)).to eq "18/10/2013 13:54:04" 9 | end 10 | end 11 | 12 | context "when date format is %d/%m/%Y" do 13 | it "returns a formated string" do 14 | string = "25/02/2016 09:22:26" 15 | expect(RubyDanfe::Helper.format_datetime(string)).to eq "25/02/2016 09:22:26" 16 | end 17 | end 18 | end 19 | 20 | describe ".format_date" do 21 | it "returns a formated string" do 22 | string = "2013-10-18" 23 | expect(RubyDanfe::Helper.format_date(string)).to eq "18/10/2013" 24 | end 25 | 26 | it "returns a formated string" do 27 | string = "" 28 | expect(RubyDanfe::Helper.format_date(string)).to eq "" 29 | end 30 | end 31 | 32 | describe ".format_time" do 33 | it "returns a formated string" do 34 | string = "22:30:45" 35 | expect(RubyDanfe::Helper.format_time(string)).to eq "22:30:45" 36 | end 37 | 38 | it "returns a formated string" do 39 | string = "" 40 | expect(RubyDanfe::Helper.format_time(string)).to eq "" 41 | end 42 | end 43 | 44 | describe ".format_quantity" do 45 | context "with RubyDanfe.options.numerify_prod_qcom false" do 46 | before(:each) { 47 | RubyDanfe.options.numerify_prod_qcom = false 48 | } 49 | it "should replace last dot for comma" do 50 | expect(RubyDanfe::Helper.format_quantity("100.00")).to eq "100,00" 51 | end 52 | it "should replace all commas for dot except the last one" do 53 | expect(RubyDanfe::Helper.format_quantity("2,100.00")).to eq "2.100,00" 54 | end 55 | it "should do anything if there is no comma and dot" do 56 | expect(RubyDanfe::Helper.format_quantity("100")).to eq "100" 57 | end 58 | it "should keep decimals" do 59 | expect(RubyDanfe::Helper.format_quantity("1.665")).to eq "1,665" 60 | end 61 | end 62 | 63 | context "with RubyDanfe.options.numerify_prod_qcom true" do 64 | context "with quantity_decimals = 4" do 65 | before(:each) { 66 | RubyDanfe.options.numerify_prod_qcom = true 67 | RubyDanfe.options.quantity_decimals = 4 68 | } 69 | it "should format number to 4 decimal places" do 70 | expect(RubyDanfe::Helper.format_quantity("100.00")).to eq "100,0000" 71 | end 72 | it "should format number with thousand separator" do 73 | expect(RubyDanfe::Helper.format_quantity("8956100.00")).to eq "8.956.100,0000" 74 | end 75 | it "should format number without dot and comma" do 76 | expect(RubyDanfe::Helper.format_quantity("200")).to eq "200,0000" 77 | end 78 | end 79 | 80 | context "with quantity_decimals = 3" do 81 | before(:each) { 82 | RubyDanfe.options.numerify_prod_qcom = true 83 | RubyDanfe.options.quantity_decimals = 3 84 | } 85 | it "should format number to 4 decimal places" do 86 | expect(RubyDanfe::Helper.format_quantity("100.00")).to eq "100,000" 87 | end 88 | it "should format number with thousand separator" do 89 | expect(RubyDanfe::Helper.format_quantity("8956100.00")).to eq "8.956.100,000" 90 | end 91 | it "should format number without dot and comma" do 92 | expect(RubyDanfe::Helper.format_quantity("200")).to eq "200,000" 93 | end 94 | end 95 | end 96 | end 97 | 98 | describe ".format_cnpj" do 99 | context "with a valid cnpj" do 100 | it "returns a formated string" do 101 | string = "15704602000105" 102 | expect(RubyDanfe::Helper.format_cnpj(string)).to eq "15.704.602/0001-05" 103 | end 104 | end 105 | 106 | context "with an invalid cnpj" do 107 | it "returns an empty string" do 108 | string = "157046020" 109 | expect(RubyDanfe::Helper.format_cnpj(string)).to eq "" 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /spec/lib/options_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe RubyDanfe::Options do 4 | it "should return default config set in code" do 5 | options = RubyDanfe::Options.new 6 | expect(options.quantity_decimals).to eq(2) 7 | end 8 | 9 | it "should return config set in params" do 10 | options = RubyDanfe::Options.new({"quantity_decimals" => 4}) 11 | expect(options.quantity_decimals).to eq(4) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/lib/ruby_danfe_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe RubyDanfe do 4 | let(:base_dir) { "./spec/fixtures/"} 5 | let(:output_pdf) { "#{base_dir}output.pdf" } 6 | 7 | before { 8 | File.delete(output_pdf) if File.exist?(output_pdf) 9 | RubyDanfe.options = {"quantity_decimals" => 2} 10 | } 11 | 12 | describe ".generate" do 13 | it "saves the PDF document to file based on a xml file" do 14 | expect(File.exist?(output_pdf)).to be_falsey 15 | 16 | RubyDanfe.generate(output_pdf, "#{base_dir}nfe_with_ns.xml") 17 | 18 | expect("#{base_dir}nfe_with_ns.xml.fixture.pdf").to be_same_file_as(output_pdf) 19 | end 20 | end 21 | 22 | describe ".render" do 23 | it "renders the PDF document to string based on a xml string" do 24 | xml_string = File.new("#{base_dir}nfe_with_ns.xml") 25 | 26 | pdf_string = RubyDanfe.render(xml_string) 27 | 28 | expect(pdf_string).to include '%PDF-1.3' 29 | end 30 | end 31 | 32 | describe ".render_file" do 33 | it "renders the PDF document to file based on a xml string" do 34 | expect(File.exist?(output_pdf)).to be_falsey 35 | 36 | xml_string = File.new("#{base_dir}nfe_with_ns.xml") 37 | 38 | RubyDanfe.render_file(output_pdf, xml_string) 39 | 40 | expect("#{base_dir}nfe_with_ns.xml.fixture.pdf").to be_same_file_as(output_pdf) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "simplecov" 2 | SimpleCov.start 3 | 4 | require "bundler/setup" 5 | require "ruby_danfe" 6 | require 'rake' 7 | 8 | Bundler.require(:default, :development) 9 | Dir[File.dirname(__FILE__) + "/support/*.rb"].each { |f| require f } 10 | 11 | load File.expand_path("../../Rakefile", __FILE__) 12 | Rake::Task["spec:fixtures:recreate_pdfs"].invoke 13 | # rake spec:fixtures:recreate_pdfs 14 | 15 | RSpec.configure do |config| 16 | config.expect_with :rspec do |c| 17 | c.syntax = :expect 18 | end 19 | 20 | config.order = "random" 21 | end 22 | -------------------------------------------------------------------------------- /spec/support/be_same_file_as.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define(:be_same_file_as) do |exected_file_path| 2 | match do |actual_file_path| 3 | expect(md5_hash(actual_file_path)).to eq(md5_hash(exected_file_path)) 4 | end 5 | 6 | def md5_hash(file_path) 7 | Digest::MD5.hexdigest(File.read(file_path)) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/cteos.xml: -------------------------------------------------------------------------------- 1 | 33000000185357Prestação de serv. de transp. a não contribuinte671182017-12-04T15:37:35-02:001171001.03301009CAMPOS DOS GOYTACAZESRJ01693301009CAMPOS DOS GOYTACAZESRJ3302403MACAÉRJ2896381700018485105167AUTO VIACAO ESPERANCA LTDAAUTO VIACAO ESPERANCA LTDARUA IVES BAZETTE DOS SANTOS2452GUARUS3301009CAMPOS DOS GOYTACAZES28083485RJ999999999948122295002653FMC- TECHNOLOGIES DO BRASIL LTDA2227370718Rodovia Amaral PeixotoKM187Cabiunas3302403MACAÉ27970020RJ1058Brasil22100.0022100.009090.002210.0020.00442.000.00SERVICO DE TRANSPORTE46.0000000000000000LNW499000778000451RJLCuhPkbUeGfnTyMceIHclO/pvMY=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1RS20171130100518331712289638170001846700100000001810000001872017-12-04T15:37:37-02:00333170022629033LCuhPkbUeGfnTyMceIHclO/pvMY=100Autorizado o uso do CT-e -------------------------------------------------------------------------------- /test/danfe.xml: -------------------------------------------------------------------------------- 1 | 3580000042RETORNO/INDUSTRIALIZAÇÃO EFETUADA PARA OUTRO ESTABELECIMENTO155120952014-03-12135231071101132.2.2159374918000143TECNOLIGAS INDÚSTRIA E COMÉRCIO DE METAIS LTDATECNOLIGASRUA COBALTO19CORREDOR INDUSTRIAL3523107ItaquaquecetubaSP085861201058BRASIL0114648664437902942011062962452100145581238000196DAISA INDUSTRIA METALURGICA LTDAAV HELIO OSSAMU DAIKUARA1800 BVISTA ALEGRE3515004EmbuSP068070001058BRASIL114704552229800652911702RECUPERACAO DE BORRA DE ALUMINIO (TRANSFORMACAO PARA LINGOTES)760200005124KG3323.00001.25000000004153.75KG3323.00001.2500000000101012.84117.9607699951024153.750.2811.63024153.751.1648.1814RETORNO DE MERCADORIA RECEBIDA PARA TRANSFORMACAO PARA LINGOTES DE ALUMINIO760200005902KG5200.00003.000000000015600.00KG5200.00003.000000000010400076999530808MATERIAL DE VOSSA PROPR. CF NF Nº 026.039 DE 07/03/2014, QUE RETORNAM TRANSFORMADOS EM LINGOTES DE ALUMINIO COM QUEBRA = 1.877 KG.0.000.000.000.0019753.750.000.000.000.000.0011.6348.180.0019753.75159374918000143TECNOLIGAS INDUSTRIA E COMERCIO DE METAIS LTDA379029420110RUA COBALTO, 19ItaquaquecetubaSPA GRANELS/MS/N5200.0005200.00020954153.754153.752095/12014-04-114153.75EMPRESA OPTANTE PELO SIMPLES NACIONAL.bAGJFpwJ1TznKGjrfj3nAV6+pIs=SPGXJgTe1J2XByj2l6MmvtXw9W1J0nAu8tf809v6r/appFbkEGeLcvbW26u53DGCSiWTt9oiUmUH 2 | hph/GNYVN1WVDK55UhpetP7xDd5qHsg0X/vyrUXBoT+IZ0O28FF/Ndwu+hCrB6xYwZCGQmGkRQ7G 3 | TZvMvMjvm74/jAE2XNNGZOc0qHPqn0DnIadMD6aYX4eo/Y9JXpPrSzrR1r47MlHfFPP2VsyoQ6+F 4 | 3XHhNW6yfVdxGbsxVvrgAaX41CgbU7mZZwG63Tx3M3COmwFYRuOpZBugvPGOVmgtooDETv9fcrFS 5 | Kyga49JFCoPuYoF3Ch1XnA3gusvc5Q9GZxSfdA==MIIIZDCCBkygAwIBAgIQHCgWAi5evL0ekPewJ3yeijANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQG 6 | EwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRh 7 | IEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYDVQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4X 8 | DTEyMDUxMTAwMDAwMFoXDTE1MDUxMDIzNTk1OVowggEMMQswCQYDVQQGEwJCUjETMBEGA1UEChQK 9 | SUNQLUJyYXNpbDELMAkGA1UECBMCU1AxGDAWBgNVBAcUD0lUQVFVQVFVRUNFVFVCQTE2MDQGA1UE 10 | CxQtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRYwFAYDVQQL 11 | FA1SRkIgZS1DTlBKIEEzMSYwJAYDVQQLFB1BdXRlbnRpY2FkbyBwb3IgQVIgR3VhcnVmb3J0ZTFJ 12 | MEcGA1UEAxNAVEVDTk9MSUdBUyBJTkRVU1RSSUEgRSBDT01FUkNJTyBERSBNRVRBSVMgTFREQSBF 13 | UDo1OTM3NDkxODAwMDE0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmyIeuvBdoj 14 | hMC73wPtiu59bW/u2DplnOv1pl9OkyHrd1+k6uHwsLXjDcf54mEJ9fJtZXvp4iVkHiJ1pCw4BEzx 15 | +PhBdzvix5wMGztlcqk2aN7dQtqr/8L7b6ARDpGIRVZoHUCC+6PwxtIYgA/DSFfAe1fqHBQr4vkD 16 | rEcJGZ/EsyZASsUgkdOkzO9/XlUaCGds1nQ3R1kiSeakglgRG6QMwKIYlgV/N/DYhS/F0Yioa1Go 17 | 16zpo7OaOh1LBgxtLaEbtqWcE3Sd7GMcnSI2qnFshSjOKVj0RNQgFgZVSDofqjvLscLBxkS820qH 18 | O+Mj2Sn8DCY387i4ngxIcydq4gkCAwEAAaOCA1IwggNOMIG3BgNVHREEga8wgaygOAYFYEwBAwSg 19 | LwQtMTUxMDE5NjIwMTI4ODU5MDgzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwoCMGBWBMAQMC 20 | oBoEGEFHTkFMRE8gQk9ORVRURSBQT0xJRE9SSaAZBgVgTAEDA6AQBA41OTM3NDkxODAwMDE0M6AX 21 | BgVgTAEDB6AOBAwwMDAwMDAwMDAwMDCBF3RlY25vbGlnYXNAdGVycmEuY29tLmJyMAkGA1UdEwQC 22 | MAAwHwYDVR0jBBgwFoAULpHq1m3lslmC3DiFKXY0FlY80D4wDgYDVR0PAQH/BAQDAgXgMH8GA1Ud 23 | IAR4MHYwdAYGYEwBAgMGMGowaAYIKwYBBQUHAgEWXGh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2ln 24 | bi5jb20uYnIvcmVwb3NpdG9yaW8vZHBjL0FDX0NlcnRpc2lnbl9SRkIvRFBDX0FDX0NlcnRpc2ln 25 | bl9SRkIucGRmMIIBFgYDVR0fBIIBDTCCAQkwV6BVoFOGUWh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRp 26 | c2lnbi5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0ZXN0Q1JMLmNy 27 | bDBWoFSgUoZQaHR0cDovL2ljcC1icmFzaWwub3V0cmFsY3IuY29tLmJyL3JlcG9zaXRvcmlvL2xj 28 | ci9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5jcmwwVqBUoFKGUGh0dHA6Ly9yZXBvc2l0b3Jp 29 | by5pY3BicmFzaWwuZ292LmJyL2xjci9DZXJ0aXNpZ24vQUNDZXJ0aXNpZ25SRkJHNC9MYXRlc3RD 30 | UkwuY3JsMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDCBmwYIKwYBBQUHAQEEgY4wgYsw 31 | XwYIKwYBBQUHMAKGU2h0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2lnbi5jb20uYnIvcmVwb3NpdG9y 32 | aW8vY2VydGlmaWNhZG9zL0FDX0NlcnRpc2lnbl9SRkJfRzQucDdjMCgGCCsGAQUFBzABhhxodHRw 33 | Oi8vb2NzcC5jZXJ0aXNpZ24uY29tLmJyMA0GCSqGSIb3DQEBCwUAA4ICAQDPdVSjPZ7tdTx4pCHV 34 | OOmbEJ5PP5RkTvZ1FCspjJ5jNSNqrGAp/dm19OeTg0rBeqZ+SJgA6TuinpgtGL+vwtMquDGeLLef 35 | n7Df/OKtrLJkfK+vfTpK6MuJBahmI8nyHv5ouoSBEpJ8byDo1a+OSgXAaYsBasC0I3shpdLdzZ1h 36 | k35x6kUlEirQyHMtbxlOAw+HfzQmv+1qOZpt3ElbC1CtR1Bun56JC5YuiOAd03OhJP01JAnzw5Ze 37 | XnAfmEQh35310+PLTnJAD8mdPNMXdZAXBhIspyDMy/gM2ou5R/9k5coK2fTcwjqH0atL9ezGnBqB 38 | vH9txy8ArcdWrosjLuNrbOq4fqrK8PjUZKVptBYMh4nEMwf8uI2ega1E+0TEwIFx7TnVvUR3U3DO 39 | u2Zl/U+9Pc16LBRAubafO68PnGn9IeEgLE5dL1mkG34lHxhU4oLF7q631divGR4B5DIA/UjhiRnJ 40 | nsGL+STa2q3i5sOMfuhhhr3UIVg/xkbeFZHx+NK/1BJe1/eDmiK4eofAYVCzhb1yRHWotDJMQ6yq 41 | dVvIdpia77H57h02bwtd0YoQ8yC8daVH0roZONE2klI55XrThX7GV372Vm/K03anTZS9KKDpzXMu 42 | THTsT17MV8IxuMX21LRkitKSO4Y6l+C6Y09bT/MX/rQSBNopxtLgBPu8iQ==1SP_NFE_PL_006q351403593749180001435500100000209518000004202014-03-12T10:41:31135140152647164bAGJFpwJ1TznKGjrfj3nAV6+pIs=100Autorizado o uso da NF-e -------------------------------------------------------------------------------- /test/generate.rb: -------------------------------------------------------------------------------- 1 | require "../lib/ruby_danfe" 2 | 3 | if ARGV.size == 0 4 | puts "Usage: generate.rb " 5 | exit(1) 6 | end 7 | 8 | type = (ARGV[1] || "danfe").to_sym 9 | 10 | RubyDanfe.generate("#{ARGV[0]}.pdf", ARGV[0], type) 11 | -------------------------------------------------------------------------------- /test/generate_nfce.rb: -------------------------------------------------------------------------------- 1 | require "../lib/ruby_danfe" 2 | 3 | if ARGV.size == 0 4 | puts "Usage: generate.rb " 5 | exit(1) 6 | end 7 | 8 | RubyDanfe.generate("nfce.pdf", ARGV[0], :danfe_nfce) -------------------------------------------------------------------------------- /test/nfce.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 6 | 59290096 7 | VENDA DE MERCADORIA 8 | 0 9 | 65 10 | 2 11 | 639 12 | 2013-11-29T16:29:02-04:00 13 | 1 14 | 1 15 | 1302603 16 | 4 17 | 1 18 | 8 19 | 1 20 | 1 21 | 1 22 | 1 23 | 0 24 | ATXOne - 1.0.0.22 25 | 26 | 27 | 02547812000112 28 | EMPRESA DE TESTE 29 | TRES ELEFANTES 30 | 31 | AV CORONEL TEIXEIRA 32 | 5705 33 | LOJA 83/84.1 1 PISO SHOPPING PONTA NEGRA 34 | Ponta Negra 35 | 1302603 36 | MANAUS 37 | AM 38 | 69037000 39 | 1058 40 | BRASIL 41 | 9236677413 42 | 43 | 053429737 44 | 1 45 | 46 | 47 | 48 | 940 49 | 9000000009400 50 | BRINCO VANIA VARIADOS 10 51 | 71171900 52 | 5102 53 | UN 54 | 1.0000 55 | 15.9000000000 56 | 15.90 57 | 9000000009400 58 | UN 59 | 1.0000 60 | 15.9000000000 61 | 1 62 | 63 | 64 | 65 | 66 | 2 67 | 102 68 | 69 | 70 | 71 | 72 | 01 73 | 0.00 74 | 0.00 75 | 0.00 76 | 77 | 78 | 79 | 80 | 01 81 | 0.00 82 | 0.00 83 | 0.00 84 | 85 | 86 | 87 | 88 | 89 | 90 | 0.00 91 | 0.00 92 | 0.00 93 | 0.00 94 | 15.90 95 | 0.00 96 | 0.00 97 | 0.00 98 | 0.00 99 | 0.00 100 | 0.00 101 | 0.00 102 | 0.00 103 | 15.90 104 | 105 | 106 | 107 | 9 108 | 109 | 110 | 01 111 | 15.90 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | ajtb/i2P6/vr/TT8rbul0os5JZQ= 125 | 126 | 127 | I/TFfNRId9s4ge2d/fp4Lfl3Txb9X4OArxF5LLyLYnuLmvEJL5ALCf85a1jnJUhxVAJzT+pVD0QuMt/VZKhaVUOmE0ZOmv/yxp9J+aQnioig54z444zpwEhc037+fh3EKVelb4dNiD6tHLjf7rykA6p+gZ7JrKKLcAttdQWr40Ei0/tWPnZ4SsDM/G3EdrKRuNlmERbJRTc3+8zhN2n3Tz5stFl1ExGUVJgXUOqKO8h+4rtclWlk9w6K7ZnFE420kjzSuPW4CBz4glZ3EVJk7bOeFRbuaOBH7G/r1zAaSKc80rK7hHcw8cskHf7JXc0rYHTHA65CgdapPeOSLBhhbw== 128 | 129 | 130 | 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 131 | 132 | 133 | 134 | 135 | 136 | 137 | 1 138 | AM2.00 139 | NFe131311188353120001806500200000063915929078898 140 | 2013-11-29T16:29:00 141 | 113130105846418 142 | ajtb/i2P6/vr/TT8rbul0os5JZQ= 143 | 100 144 | Autorizado o uso da NF-e 145 | 146 | 147 | -------------------------------------------------------------------------------- /test/nfe_simples_nacional.xml: -------------------------------------------------------------------------------- 1 | 35000000016101-Venda de producao do estabelecimento155112013-12-2813550308116110160891033000109KRON INSTRUMENTOS ELETRICOS LTDAKRON INSTRUMENTOS ELETRICOS LTDARUA ALEXANDRE DE GUSMAO278SOCORRO3550308SAO PAULOSP047600201058BRASIL1155252000111393871117182743287000880Schneider Electric Brasil LtdaAv da Saudade1125Frutal3552403SUMARESP131713201058BRASIL19210463006710083751101Tijolo Macico Tipo A69041000006101MI2.000010.000000000020.00MI2.000010.000000000015.350102990.000.000.00990.000.000.002Tijolo Macico Tipo B69041000006101MI3.000020.000000000060.00MI3.000020.0000000000116.050102990.000.000.00990.000.000.003Tijolo Macico Tipo C69041000006101MI4.000030.0000000000120.00MI4.000030.0000000000132.100102990.000.000.00990.000.000.000.000.000.000.00200.000.000.000.000.000.000.000.000.00200.0053.500112014-01-2740.0022014-02-2640.0032014-03-2840.0042014-04-2740.0052014-05-2740.00DOCUMENTO EMITIDO POR ME OU EPP OPTANTE PELO SIMPLES NACIONAL * NAO GERA DIREITO A CREDITO FISCAL DE IPI * Tributos: R$ 53,50 (26,75%) 2 | -------------------------------------------------------------------------------- /test/nfe_with_fci.xml: -------------------------------------------------------------------------------- 1 | 3563472050VENDA DE PRODUCAO DO ESTABELECIMENTO1551445252013-10-18135503081151105.060891033000109KRON INSTRUMENTOS ELETRICOS LTDAKRONRUA ALEXANDRE DE GUSMAO278SOCORRO3550308SAO PAULOSP047600201058BRASIL1155252000111393871117382743287000880SCHNEIDER ELECTRIC BRASIL LTDAAV. DA SAUDADE1125FRUTAL3552403SUMARESP131713201058BRASIL1921046300671008375110nfemerc.sumare@br.schneider-electric.comF211130101000AMPERIMETRO FM72PC 300/5A COD 3491192843 RL90303329005101PC1.0049.2349.23PC1.0049.231980019211012232531-74B2-4FDD-87A6-CF0AD3E55386500349.2312.005.909995049.235.002.460149.230.650.320149.233.001.4849.235.900.000.0049.230.000.000.000.002.460.321.480.0051.69050547058000128POST MASTER COMERCIAL LTDA111768652113RUA VIEIRA DE MORAES 558SAO PAULOSP1CAIXAKRON11.0001.0000044525/012013-12-1751.69FRETE CIF / INDUSTRIALIZACAO PEDIDO 98001921 VENC. DAS DUPLICATAS 01/ 10 / 20 DO MES - VIA DEPOSITO [EMAIL=nfemerc.sumare@br.schneider-electric.com]98001921dndW1koiOiYKZkXf7cWtg5vfL2Y=JXN6WtG/sLQgtEI0n0BhajaphVDAX99A+QcrC3XxTkP4vZ/yHpwr2ngvs3t0M1uLECymakCxjT/qMmanJDiaAGxfWmBJkdgDFa80zJ2RoS9RqF48QmNXHfDNtjwwgw12RlFC8reLWGw7qXD9Nre5E9bTWJqEH4RHhKcg/akiWsQ2uy6M2O/m3IgznCG6wMnhaE98BbXTqcHLrvRignT86HQssaV6DDVm2kXyL1FM8YMZF3TtbsMQ8PJs70FrwddVzFIPoYxSq7iBw40ZdveuexYApVYJdyUssBZcxnlWtaS9aOWpd1fqHiQy5fKRRycBwOdMEPcQXGKqkNUs1hlUtg==MIIIQjCCBiqgAwIBAgIQdHnQdADNdDiHWqCYm1mh6zANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYDVQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4XDTEzMDIyNTAwMDAwMFoXDTE0MDIyNDIzNTk1OVowgfExCzAJBgNVBAYTAkJSMRMwEQYDVQQKFApJQ1AtQnJhc2lsMQswCQYDVQQIEwJTUDESMBAGA1UEBxQJU0FPIFBBVUxPMTYwNAYDVQQLFC1TZWNyZXRhcmlhIGRhIFJlY2VpdGEgRmVkZXJhbCBkbyBCcmFzaWwgLSBSRkIxFjAUBgNVBAsUDVJGQiBlLUNOUEogQTExIjAgBgNVBAsUGUF1dGVudGljYWRvIHBvciBBUiBGQUNFU1AxODA2BgNVBAMTL0tST04gSU5TVFJVTUVOVE9TIEVMRVRSSUNPUyBMVERBOjYwODkxMDMzMDAwMTA5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs7JenW0yMGg/bzp+ByFBjxG2nxE9DvzegNzr9NzH+ob+9nCm2iCDaB12dytrPD9aJYXE9Y4AcO+R8a5iUkTaGS4fGAfT11JSNyFLmatR+Z5AJZZ4j0N6g5moRWxOShPjoqxPf43IpAFwQrb2AhWi+wrTtwbS89jvVonGQvEdQsS1zkzX7KWvvy2bFcUCupvXd+TP0aIdyi2XjCkpGT0j3T1qvZrz2WnbhWW4VqZVfXiVZyYhijgbi+IO7s5wrYVTJCZtNvoffRsmGh+aTTlGgapjatWN+3u+M885Y4umFBqEmGgWxoidO1xXiURYhkLF5w2wlxJlwcC0qsF2wpuPOwIDAQABo4IDTDCCA0gwgbEGA1UdEQSBqTCBpqA4BgVgTAEDBKAvBC0yOTA3MTk1NTAxMjU1MzE4ODU2MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCgJQYFYEwBAwKgHAQaRkVSTkFORE8gTUFSQ0hFVFRJIEJFRElDS1OgGQYFYEwBAwOgEAQONjA4OTEwMzMwMDAxMDmgFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwgQ9jcGRAa3Jvbi5jb20uYnIwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBQukerWbeWyWYLcOIUpdjQWVjzQPjAOBgNVHQ8BAf8EBAMCBeAwfwYDVR0gBHgwdjB0BgZgTAECAQwwajBoBggrBgEFBQcCARZcaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9kcGMvQUNfQ2VydGlzaWduX1JGQi9EUENfQUNfQ2VydGlzaWduX1JGQi5wZGYwggEWBgNVHR8EggENMIIBCTBXoFWgU4ZRaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9sY3IvQUNDZXJ0aXNpZ25SRkJHNC9MYXRlc3RDUkwuY3JsMFagVKBShlBodHRwOi8vaWNwLWJyYXNpbC5vdXRyYWxjci5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0ZXN0Q1JMLmNybDBWoFSgUoZQaHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5nb3YuYnIvbGNyL0NlcnRpc2lnbi9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5jcmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGbBggrBgEFBQcBAQSBjjCBizBfBggrBgEFBQcwAoZTaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9jZXJ0aWZpY2Fkb3MvQUNfQ2VydGlzaWduX1JGQl9HNC5wN2MwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmNlcnRpc2lnbi5jb20uYnIwDQYJKoZIhvcNAQELBQADggIBAK22zXyUD+FxXBLcP99DfElExHg7a8ZIqCNQs58pG5xR5rNYib46z6tGmEsWCbgViagokqdyQmLNAfE/t1UqOdu4dxMoQM2m5O3Nk/PDOaVVe5y93dFBOr5xMQsfQFtcHbWO0QTeJdG0Uh0LxhRVriPH9JmvAMPUjUl9W/+/hIjohh/zVDyX8WfBKRvVqn/RbFaBSyoYiLDBQWZ4FecrcqX/IXViSDM4d6jFS7+6OSFHgxzl08M4zAqaaSD51IQ3N9fcdhTolVAgHSNNMou88eJaRhbMGtX5qciiUbDTgaX69VbPWeSKtA3TpHKMvNidZTfhhu8X/MxqztTpEEUrKfxRLkIUdVkho3a2/GfD3ePcy7k+Zexu2u1vTkXSGXKDvrJkowOXI11Xob6CP6ZNCCaftdQ+8WA+kZpthjILhY6G7jYy20OFiPTPLwC70funz+wkAB2upX7fMkxctTuAEEbecwcshJS4IgOJCOWPjuOFVMrCOKi1xgPZTxmmHZ9JcVik2Z7JlwV2r+j2sjAYYCFExipw2PmbTDtSL3worhASMsllWYaSmGM524aPEWXiemR0zfKEUuS5wDBdFJrsZkjJDIFJs0AmP2rXf2ftoN73g/ap2ycqbgpt5NYBhhN1az9sc/n6062WatrXVrj94Vx8j+8j6L42Qwx+PrB9Fzrr1SP_NFE_PL_006q351310608910330001095500100004452516347205052013-10-18T13:54:04135130636167763dndW1koiOiYKZkXf7cWtg5vfL2Y=100Autorizado o uso da NF-e 2 | -------------------------------------------------------------------------------- /test/nfe_with_ns.xml: -------------------------------------------------------------------------------- 1 | 2500013415Vendas de producao do estabelecimento1552134152011-10-292011-10-2912507507111110Integrat12345678901234ACME SAACME-PBRUA HORTENCIO RIBEIRO DE LUNA3333DISTRITO INDUSTRIAL2507507Joao PessoaPB580814001058BRASIL8321062200160158257398765432101234EDITORA BLEBLEBLE LTDARUA URBANO SANTOS, N755 (ANT 160)0CUMBICA3518800GuarulhosSP071823201058BRASIL1127901347336322171116 2 | 00005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.9400100030.000.000.00010.000.000.00010.000.000.00 3 | 00005LIVRO POR LIT GRAMATICA PROD TEXTO 3a SERIE ALUNO490199006101UN28080.00003.9400110635.20UN28080.00003.940010202456.00100.00479.8217.0029.28010.000.000.00010.000.000.00 4 | 0.000.00479.820.00110635.200.000.000.000.000.000.000.000.00110635.20010849477000108TRANSPRINT - TRANSPORTADORA E LOGISTICA LTDA148613972111Rua do TatuapeSAO PAULOSP00000000SP00000026VOLUMES(s)DIVERSOS025000.00025000.00013415//1110635.20110635.2013415//1-12012-02-26110635.20Obs: PEDIDO DE COMPRA: 308.996 MATERIAL IMUNE CONFORME ART.150 INCISO VI ALINEA D DA CONSTITUICAO FEDERAL.9jeTTSaza8lMT2Xk5hbWx86Fbp4=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1SVRS20110801092042251110123456789012345500200001341510001341512011-10-29T14:37:093251100128663209jeTTSaza8lMT2Xk5hbWx86Fbp4=100Autorizado o uso da NF-e 5 | -------------------------------------------------------------------------------- /test/nfe_without_ns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3191136050REMESSA MERC. P/ CONSERTO055100121182013-02-22131186011171105.099984626000136ACME SAACMEVIA EXPRESSA DE CONTAGEM3850CINCAO3118601CONTAGEMMG323704851058BRASIL31339966001862422430000398765432101234BLABLABLA LTDAAV. MARGINAL DO RIB. DOS CRISTAIS200JORDANESIA3509205CAJAMARSP077600001058BRASIL3130698013241029868119F-MERCPCMONITOR DE ARCO ELETRICO COD:1-VAMP2213A3AAA NS: V221-00663085369090006915pc1.004491.254491.25pc1.004491.25109030.000.000.0040.000.000.00999510707F-MERCPCDETECTOR FALHA ISOLAMENTO COD:1-XD312127-01 NS: 1518385V185369090006915pc1.001588.701588.70pc1.001588.70109030.000.000.0040.000.000.00999510707F-MERCPCMONITOR DE ARCO ELETRICO COD:1-VAMP2213A3AAA NS: V221-00682485369090006915pc1.004038.754038.75pc1.004038.75109030.000.000.0040.000.000.009995107070.000.000.000.0010118.700.000.000.000.000.000.000.000.0010118.70020147617000141JAMEF TRANSPORTADORA LTDA0624426220024RUA DR JOSE AMERICO CANCADO BAHIA 1810CONTAGEMMG2.10.00010.000MATERIAL DE NOSSA PROPRIEDADE QUE SEGUE PARA REPAROS, DEVENDO RETORNAR AO NOSSO ESTABELECIMENTO. **** ICMS SUSPENSO CONF.ART.19 ITEM 1 ANEXO III DEC.43080 IPI SUSPENSO CONF.ART.42 INCISO XIII DEC.4544 DEZ/02 ROMA-491 | Cod.Repart.Fiscal: 00001CAmkmMtOyPC1hfWU/LLGQUdAZ6Q=KRFiDTL4BlsIBBers9uAdAx9DF7eVrYkDU3Wgo/jqD1jhYHNWNe4UFCiQYamLuRKi+gpxd6e7zXEprt9LZ8qVI5ttwn324w90l2v0L5J1aqqRFI5SY8OAO0Y2HIYtrrPuoZwwG5LKr93W8vj/6oOFJZW2VQVSbjyXK2PfcW2ruV8W2RE23cd61LBcH2Vh7qrKaPCoQ0jjDVTjVy8+K5Dz8KXdTCkarRK88rgqfFalj3xQ3uFs7KBeAEkPPvU1ZR5PFnTbBJw10Y5jwlC52A0d66ts1oowdbSKeCjkiCAOxn0+IrG//iKiZWFByRqbScrh4jCR4gt++GPklTFCU/jAA==MIIHtjCCBZ6gAwIBAgIQMjAxMjA4MjcxODQ5MDA1OTANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEgZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEuMCwGA1UEAxMlQXV0b3JpZGFkZSBDZXJ0aWZpY2Fkb3JhIFNFUlBST1JGQiB2MzAeFw0xMjA4MjcxODU0MTlaFw0xMzA4MjcxODUzNTdaMIH2MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMREwDwYDVQQLEwhNQVhYREFUQTETMBEGA1UECxMKQVJNQVhYREFUQTEWMBQGA1UECxMNUkZCIGUtQ05QSiBBMTERMA8GA1UEBxMIQ09OVEFHRU0xCzAJBgNVBAgTAk1HMTowOAYDVQQDEzFPUlRFTkcgRVFVSVBBTUVOVE9TIEUgU0lTVEVNQVMgUyBBOjE5ODg0NjI2MDAwMTM2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkLSjqD7kjA/wh+kxGNtwcKLdfsf0orqlb9wRkhsmaYE2TwJpx9CjjuI1A1KkTioJzlT/geuhtEbEKMQxadlXsUhLIV97dDc+m8F4CIpgOe6qMvR3sX9GBoQ9WL2Hdu29KwrpuYiRs7VXu+oOtq67QFJisQ8URGY48FCNvQP1SzguZiOIgV6pw9oqQG7jWWr8eZa4eXwdZ6+2jKX7GWwiTBNGf5q9as+ISkpG5Ij5t8I6xV/tVxB5u719KiRysAAfRDB8zbDhK6xpELwdmZgStrYUnAUFNYlwcMIDtXqr3iSm1v8x8KQeSo5yCDwDuB33UatnltPujsaKSKdqJHD25wIDAQABo4ICqDCCAqQwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSxZ7Ed5xyud0IUrX+eCQ7mhbC3rjAOBgNVHQ8BAf8EBAMCBeAwYAYDVR0gBFkwVzBVBgZgTAECAQowSzBJBggrBgEFBQcCARY9aHR0cHM6Ly9jY2Quc2VycHJvLmdvdi5ici9hY3NlcnByb3JmYi9kb2NzL2RwY2Fjc2VycHJvcmZiLnBkZjCBywYDVR0RBIHDMIHAoD0GBWBMAQMEoDQEMjE0MDgxOTcyOTY4Mzg4NDE2NDkxMjI4MjI1NDE2NTAwMDAwMTY4MjUxODI2NUROVE1HoC0GBWBMAQMCoCQEIlJPRFJJR08gTkVMU09OIERFIFNFTk5BIFNPVVNBIExJTUGgGQYFYEwBAwOgEAQOMTk4ODQ2MjYwMDAxMzagFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwgRxlcm5hbmUucGVpeG90b0BvcnRlbmcuY29tLmJyMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDCBwAYDVR0fBIG4MIG1MDSgMqAwhi5odHRwOi8vY2NkLnNlcnByby5nb3YuYnIvbGNyL2Fjc2VycHJvcmZidjMuY3JsMDWgM6Axhi9odHRwOi8vY2NkMi5zZXJwcm8uZ292LmJyL2xjci9hY3NlcnByb3JmYnYzLmNybDBGoESgQoZAaHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5nb3YuYnIvbGNyL3NlcnByby9hY3NlcnByb3JmYnYzLmNybDBOBggrBgEFBQcBAQRCMEAwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jY2Quc2VycHJvLmdvdi5ici9jYWRlaWFzL2Fjc2VycHJvcmZidjMucDdiMA0GCSqGSIb3DQEBCwUAA4ICAQBIMN+16Ohzx7nR3V/udK85NlFD0UJh2X9wjewGj3Iu5b8GPllq6NVXxbv6ToSrsdg32Zcs4W8xSxuVXqx+sQWbVBko6XAqkTzGPGh0JcwbOOB0qorKUmsUO4/MP2MTGzmbUC4EKMoxdSagZjis5S8bgbtChe5NMKCG3qL3j7pRopRDvPnjCgCDKpy1jamjWlMwuNLFEGhbCnUiITr6YGwarbj8RtUdJ+OTXeOAwDEd6qXOQEvazKVNM2+zbkz9Ou1Bu3IAxVHRXiOL2suUxXXruibULdeoGroXNGQOVH6tzEmlVw041cBt/oHxzdUlkWvQlSMzcgzyxUiO/cpAcW60xUSdhmtVnt/HEpvTTBOVvODD/Y+PKETv/iZ2+md4iEDGmbkPY76sAYw+zLWEdSOHLZm3HVzwkYM82XrpPhBWMfg6YFAgoXYhNY0BzITIM32DnHhFSsk/ohIopdGi+fz3fgl+Ndt+CHjge2Dibp0zx6j2bkSW2xp25+W4CvD8z/hEYVvIjOK40jmeEvyCt6e6ausdyF99Ox9e9CHXyWBt8xzicH8pj0B6GapsuFmTLlG6oITiis2qnA3LR6QlhIkI7dxQoGFBWr9OWRr66El76zm5u1SQxInJ1Tab24J80mYjMPA2vbB5n87lo3pVPwraWoHUifzxJX/YoLCl/23kLQ==113_0_61311302123456789012345510000001211819113605072013-02-22T09:32:54131131006404486CAmkmMtOyPC1hfWU/LLGQUdAZ6Q=100Autorizado o uso da NF-e --------------------------------------------------------------------------------