br_invoices_pdf 0.1.5 → 0.2.0.alpha.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +10 -0
  5. data/CHANGELOG.md +16 -0
  6. data/bin/console +5 -3
  7. data/br_invoices_pdf.gemspec +11 -8
  8. data/cfe.xml +2 -0
  9. data/lib/br_invoices_pdf.rb +36 -0
  10. data/lib/br_invoices_pdf/cfe.rb +10 -0
  11. data/lib/br_invoices_pdf/cfe/parser.rb +35 -0
  12. data/lib/br_invoices_pdf/cfe/parser/access_key.rb +19 -0
  13. data/lib/br_invoices_pdf/cfe/parser/base_parser.rb +19 -0
  14. data/lib/br_invoices_pdf/cfe/parser/company_attributes.rb +45 -0
  15. data/lib/br_invoices_pdf/cfe/parser/cpf.rb +15 -0
  16. data/lib/br_invoices_pdf/cfe/parser/document_number.rb +15 -0
  17. data/lib/br_invoices_pdf/cfe/parser/fisco_obs.rb +23 -0
  18. data/lib/br_invoices_pdf/cfe/parser/payment.rb +22 -0
  19. data/lib/br_invoices_pdf/cfe/parser/payments.rb +45 -0
  20. data/lib/br_invoices_pdf/cfe/parser/products_data.rb +37 -0
  21. data/lib/br_invoices_pdf/cfe/parser/sat.rb +25 -0
  22. data/lib/br_invoices_pdf/cfe/renderer.rb +49 -0
  23. data/lib/br_invoices_pdf/cfe/renderer/base_renderer.rb +72 -0
  24. data/lib/br_invoices_pdf/cfe/renderer/company_identification.rb +36 -0
  25. data/lib/br_invoices_pdf/cfe/renderer/fisco_info.rb +26 -0
  26. data/lib/br_invoices_pdf/cfe/renderer/header.rb +36 -0
  27. data/lib/br_invoices_pdf/cfe/renderer/payment_forms.rb +54 -0
  28. data/lib/br_invoices_pdf/cfe/renderer/product_table.rb +68 -0
  29. data/lib/br_invoices_pdf/cfe/renderer/qr_code.rb +110 -0
  30. data/lib/br_invoices_pdf/cfe/renderer/taxes_info.rb +39 -0
  31. data/lib/br_invoices_pdf/cfe/renderer/totals.rb +50 -0
  32. data/lib/br_invoices_pdf/errors/invalid_document_type.rb +12 -0
  33. data/lib/br_invoices_pdf/generator.rb +17 -0
  34. data/lib/br_invoices_pdf/version.rb +1 -1
  35. metadata +130 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c7e9c4cf2077e788b7f4db445481177a486b84d
4
- data.tar.gz: 113e1b0fc810904e1950349912076e35de99619e
3
+ metadata.gz: a9e2604496096165edb58b91671f58accaa0eee4
4
+ data.tar.gz: cf9fc31220a07ed595d3de485a061c770b239311
5
5
  SHA512:
6
- metadata.gz: 24db492318004366498b75c190111f3377238a5318a5a2f6875ffd8f6e5e3ef88a06f67576088a66044723107d8cf860b00f2758ff8e5df2c12494a87997b6b7
7
- data.tar.gz: 831db3804206236946eba51c4579dfae5b1f6e32bf254e62caaf61b11caf4a0b85fd6c75f6b3e0f7dfa44451b564342968bf5ebf01c815d2034af8749489c4a8
6
+ metadata.gz: 80f8449bf59b9453d0c018f31220f2a7c48d6cb1261219ef3de480e04e48ed88cccad1205bdeacea179db645362a67ebe2aa604ec349a54acf9dbe2b5faec2d9
7
+ data.tar.gz: 9ff89893486470aa2fd2f381f53df570fabee337ee313a97419f40ab5a7348eb00d8607f6be4fb3f4e326c86753f1fdb38b6a3cedb7a728997507294b78e66c8
data/.gitignore CHANGED
@@ -1,2 +1,5 @@
1
1
  *.gem
2
+ *.pdf
2
3
  Gemfile.lock
4
+ coverage
5
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -10,6 +10,12 @@ Metrics/ClassLength:
10
10
  Metrics/MethodLength:
11
11
  Max: 15
12
12
 
13
+ Layout/IndentArray:
14
+ Enabled: false
15
+
16
+ Layout/IndentHash:
17
+ Enabled: false
18
+
13
19
  AllCops:
14
20
  Exclude:
15
21
  - 'spec/factories/*.rb'
@@ -17,3 +23,7 @@ AllCops:
17
23
  Lint/AmbiguousBlockAssociation:
18
24
  Exclude:
19
25
  - 'spec/**/*.rb'
26
+
27
+ Metrics/BlockLength:
28
+ Exclude:
29
+ - 'spec/**/*.rb'
data/CHANGELOG.md CHANGED
@@ -4,7 +4,23 @@
4
4
 
5
5
  ### Unreleased
6
6
 
7
+ ### 0.2.0 [2017-05-29]
8
+ - [Modificado] Atualizando versões das dependências
9
+ - [Adicionado] Estrutura de Generator/Parser/Renderer
10
+ - [Adicionado] Gerador de Cfe
11
+ - [Adicionado] Cobertura de testes
12
+
13
+ ### 0.1.5 [2017-05-29]
14
+ - [Adicionado] Docs
15
+ - [Adicionado] Integração contínua
16
+ - [Adicionado] Estrutura inicial do projeto
7
17
 
8
18
  ## Informações adicionais
9
19
  - Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
10
20
  - Este projeto adere a [Semantic Versioning](http://semver.org/) e às guidelines [Keep-a-Changelog](https://github.com/olivierlacan/keep-a-changelog).
21
+ - [Adicionado] Para novas funcionalidades
22
+ - [Modificado] Para mudanças nas funcionalidades existentes.
23
+ - [Deprecado] Para funcionalidades que serão removidas no futuro.
24
+ - [Removido] Para funcionalidades removidas.
25
+ - [Corrigido] Para quaisquer correções de bugs.
26
+ - [Segurança] Para correções de vulnerabilidades.
data/bin/console CHANGED
@@ -1,4 +1,6 @@
1
- require "bundler/setup"
2
- require "br_invoices_pdf"
3
- require "irb"
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'br_invoices_pdf'
5
+ require 'irb'
4
6
  IRB.start
@@ -4,14 +4,11 @@ lib = File.expand_path('../lib', __FILE__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'br_invoices_pdf/version'
6
6
 
7
+ # rubocop:disable Metrics/BlockLength
7
8
  Gem::Specification.new do |spec|
8
9
  spec.name = 'br_invoices_pdf'
9
- spec.version = BrInvoicesPdf::VERSION
10
- if ENV['SEMAPHORE'] && ENV['PRE_RELEASE']
11
- spec.version = "#{BrInvoicesPdf::VERSION}.alpha.#{ENV['SEMAPHORE_DEPLOY_NUMBER']}"
12
- else
13
- spec.version = BrInvoicesPdf::VERSION
14
- end
10
+ pre_release = ENV['SEMAPHORE'] && ENV['PRE_RELEASE']
11
+ spec.version = BrInvoicesPdf::VERSION + (pre_release ? ".alpha.#{ENV['SEMAPHORE_DEPLOY_NUMBER']}" : '')
15
12
  spec.authors = ['Thiago Ribeiro', 'Gabriel Teles']
16
13
  spec.email = ['thiago@pdvend.com.br', 'gabriel@pdvend.com.br']
17
14
 
@@ -27,12 +24,18 @@ Gem::Specification.new do |spec|
27
24
  spec.require_paths = ['lib']
28
25
 
29
26
  spec.add_dependency 'prawn', '~> 2.2.2'
27
+ spec.add_dependency 'prawn-table', '~> 0.2.1'
30
28
  spec.add_dependency 'ox', '~> 2.5.0'
29
+ spec.add_dependency 'barby', '~> 0.5.1'
30
+ spec.add_dependency 'chunky_png', '~> 1.3.8'
31
+ spec.add_dependency 'rqrcode', '~> 0.10.1'
31
32
 
32
33
  spec.add_development_dependency 'bundler', '~> 1.13'
33
- spec.add_development_dependency 'rake', '~> 10.0'
34
+ spec.add_development_dependency 'rake', '~> 12.0'
34
35
  spec.add_development_dependency 'rspec', '~> 3.0'
35
36
  spec.add_development_dependency 'simplecov', '~> 0.14'
36
37
  spec.add_development_dependency 'coveralls'
37
-
38
+ spec.add_development_dependency 'rubocop'
39
+ spec.add_development_dependency 'reek'
40
+ spec.add_development_dependency 'byebug'
38
41
  end
data/cfe.xml ADDED
@@ -0,0 +1,2 @@
1
+ <CFe><infCFe Id="CFe35170827192750000240590002257540001395955127" versao="0.07" versaoDadosEnt="0.07" versaoSB="010002"><ide><cUF>35</cUF><cNF>595512</cNF><mod>59</mod><nserieSAT>000225754</nserieSAT><nCFe>000139</nCFe><dEmi>20170808</dEmi><hEmi>151034</hEmi><cDV>7</cDV><tpAmb>1</tpAmb><CNPJ>22769530000131</CNPJ><signAC>FO7E++TPt/v6twwElpLfq8foIU4wE4FUW0fJLU1NTZywbOGZhijk8vH5BJf7/XiefaPP2uPFtS0333ZAlmzImBycKWe0ELM2bpu0k4shuSZrAXKJtY3VDEpWRD7mibQuF7EFzy/+kKHK9G2NIajlstMa90JpbzIx2aYFvzs2SfzuT2zeIeBBsnTMutHF7NFrsZQvgHkYY4Z7/PRzRvqikxb6o1LLt6yX+d+Z40vObqJeaGzWyfVs4KOdEdyv9mOKW7RRXR0/LM0RCcudjwVHlTCjyQ3HYBsjcmkSB1HQSMgydjkJOO9ICPWP7FtMjXcDZUny2gD5BOYkqL2Byple0Q==</signAC><assinaturaQRCODE>V0t3JUTvkC9hbQrfPtsnvQpDpvx950/Qj7lQZQ9Ee6sblwhlyZUitqy/EXyb65cdwz5inSNQhbjclH00bBmhzsIId/0DcJYyWLTZ8+jid6qoQqcZVN7+85nYQwe97k9t55to6/2KtMAdn1ooB4dNLhj+2+gy2s+X6We/2I/wuEcBPgDjUynX8KTnFMeFzCtESF3D1/ykVdxj+J3E5S82emBdBNEW4DL+3+kvHsFSyqbHjsseiuTp0oz2xJUuOoD9KE63hnLbIWuOC3z69gQofgGaKWuFjICFkirtTAHBuvBsMWcaSku3HCH68/fga4W/iIbv/RenbBeecG/Ffw4X9Q==</assinaturaQRCODE><numeroCaixa>001</numeroCaixa></ide><emit><CNPJ>27192750000240</CNPJ><xNome>NUTREM VALENS COMERCIO LTDA ME</xNome><xFant>NUTREM VALENS MARKET</xFant><enderEmit><xLgr>AVENIDA WASHINGTON LUIZ</xLgr><nro>970</nro><xCpl>C</xCpl><xBairro>METROPOLE</xBairro><xMun>DRACENA</xMun><CEP>17900000</CEP></enderEmit><IE>292065728117</IE><IM>197321</IM><cRegTrib>1</cRegTrib><cRegTribISSQN>1</cRegTribISSQN><indRatISSQN>N</indRatISSQN></emit><dest></dest><det nItem="1"><prod><cProd>SUCO4233</cProd><xProd>Suco de Tangerina Integral Mitto 1L</xProd><CFOP>5405</CFOP><uCom>UND</uCom><qCom>1.0000</qCom><vUnCom>16.500</vUnCom><vProd>16.50</vProd><indRegra>A</indRegra><vDesc>1.92</vDesc><vItem>14.58</vItem></prod><imposto><vItem12741>0.00</vItem12741><ICMS><ICMSSN102><Orig>0</Orig><CSOSN>500</CSOSN></ICMSSN102></ICMS><PIS><PISSN><CST>49</CST></PISSN></PIS><COFINS><COFINSSN><CST>49</CST></COFINSSN></COFINS></imposto></det><total><ICMSTot><vICMS>0.00</vICMS><vProd>16.50</vProd><vDesc>1.92</vDesc><vPIS>0.00</vPIS><vCOFINS>0.00</vCOFINS><vPISST>0.00</vPISST><vCOFINSST>0.00</vCOFINSST><vOutro>0.00</vOutro></ICMSTot><vCFe>14.58</vCFe><vCFeLei12741>0.00</vCFeLei12741></total><pgto><MP><cMP>04</cMP><vMP>14.58</vMP></MP><vTroco>0.00</vTroco></pgto><infAdic><obsFisco xCampo="02.03.04.03"><xTexto>Consulte o QRCode deste extrato atraves do App DeOlhoNaNota</xTexto></obsFisco></infAdic></infCFe><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod><Reference URI="#CFe35170827192750000240590002257540001395955127"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod><DigestValue>x7w+x/SD/didumxuYOXNGpg9o9amGeocwTKXaC2Wt18=</DigestValue></Reference></SignedInfo><SignatureValue>a7h3NWjAwkotebkrsQpVJj0I38ztE+GQagH24O8CeYLzXqvqilWg6ygp7mheNj3eNoZWwrOI2b43pAQogarnvkGHZJfXuG+Tt1rKIF9iTS/IeA2mEg5R5CgAGYtRuQRnGKe4Ws9Es5KjT7V3kWCaDjgHwhLj4+q6fx/ItyWYrAHy/BNTdeF2BKlKGJHmpxE2sZx1erFawgEcj7I3yXqljVAch1W3Q0i7IjvzlGRpDjO36DWm3zQJYRcK9mCo6apqIPTOvOCyWS4xlLE6YF6N9oPG1doBgkZ8Iai5bv94i5aBknKt7LWh5GRU+zTGmTFxoeYIV6WBgn+51dXe5Q2BdA==</SignatureValue><KeyInfo><X509Data><X509Certificate>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</X509Certificate></X509Data></KeyInfo></Signature></CFe>
2
+
@@ -1,4 +1,40 @@
1
+ require 'ox'
2
+ require 'prawn'
3
+ require 'prawn/table'
4
+ require 'chunky_png'
5
+ require 'rqrcode'
6
+ require 'barby'
7
+ require 'barby/barcode/code_128'
8
+ require 'barby/outputter/png_outputter'
9
+ require 'barby/outputter/prawn_outputter'
10
+
1
11
  require 'br_invoices_pdf/version'
12
+ require 'br_invoices_pdf/generator'
13
+ require 'br_invoices_pdf/errors/invalid_document_type'
2
14
 
3
15
  module BrInvoicesPdf
16
+ @generators = {}
17
+
18
+ module_function
19
+
20
+ def generate(type, xml, options = {})
21
+ generator = @generators[type]
22
+ raise(Errors::InvalidDocumentType, type) unless generator
23
+ generator.generate(xml, options)
24
+ end
25
+
26
+ def register(type, renderer, parser)
27
+ raise(ArgumentError, "Expected Symbol or String to type. Received #{type.class}") unless valid_type?(type)
28
+ @generators[type.to_sym] = Generator.new(renderer, parser)
29
+ end
30
+
31
+ def supported_document_types
32
+ @generators.keys
33
+ end
34
+
35
+ def valid_type?(type)
36
+ type.is_a?(String) || type.is_a?(Symbol)
37
+ end
4
38
  end
39
+
40
+ require 'br_invoices_pdf/cfe'
@@ -0,0 +1,10 @@
1
+ require 'br_invoices_pdf/cfe/parser/base_parser'
2
+ require 'br_invoices_pdf/cfe/parser'
3
+ require 'br_invoices_pdf/cfe/renderer/base_renderer'
4
+ require 'br_invoices_pdf/cfe/renderer'
5
+
6
+ module BrInvoicesPdf
7
+ module Cfe
8
+ BrInvoicesPdf.register(:cfe, Cfe::Renderer, Cfe::Parser)
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ require 'br_invoices_pdf/cfe/parser/access_key'
2
+ require 'br_invoices_pdf/cfe/parser/company_attributes'
3
+ require 'br_invoices_pdf/cfe/parser/cpf'
4
+ require 'br_invoices_pdf/cfe/parser/document_number'
5
+ require 'br_invoices_pdf/cfe/parser/fisco_obs'
6
+ require 'br_invoices_pdf/cfe/parser/payment'
7
+ require 'br_invoices_pdf/cfe/parser/payments'
8
+ require 'br_invoices_pdf/cfe/parser/products_data'
9
+ require 'br_invoices_pdf/cfe/parser/sat'
10
+
11
+ module BrInvoicesPdf
12
+ module Cfe
13
+ module Parser
14
+ module_function
15
+
16
+ PARSERERS = {
17
+ sat_params: Sat,
18
+ document_number: DocumentNumber,
19
+ payment: Payment,
20
+ payments: Payments,
21
+ products: ProductsData,
22
+ company_attributes: CompanyAttributes,
23
+ fisco_obs: FiscoObs,
24
+ access_key: AccessKey,
25
+ cpf: Cpf
26
+ }.freeze
27
+
28
+ def parse(xml)
29
+ PARSERERS.reduce({}) do |response, (param, parser)|
30
+ { **response, param => parser.execute(xml) }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module AccessKey
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ def execute(xml)
10
+ element = xml.locate('Signature/SignedInfo').first
11
+ return unless element
12
+ element = element.nodes.last
13
+ return unless element
14
+ element.attributes[:URI]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module BaseParser
5
+ module_function
6
+
7
+ def locate_element(xml, path)
8
+ element = xml.locate(path).first
9
+ element.text if element
10
+ end
11
+
12
+ def node_locate(element, path)
13
+ value = element.nodes.first.locate(path).first
14
+ value.text if value
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module CompanyAttributes
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ SEFAZ_STATE_CODES = {
10
+ '11' => 'RO', '12' => 'AC', '13' => 'AM', '14' => 'RR', '15' => 'PA',
11
+ '16' => 'AP', '17' => 'TO', '21' => 'MA', '22' => 'PI', '23' => 'CE',
12
+ '24' => 'RN', '25' => 'PB', '26' => 'PE', '27' => 'AL', '28' => 'SE',
13
+ '29' => 'BA', '31' => 'MG', '32' => 'ES', '33' => 'RJ', '35' => 'SP',
14
+ '41' => 'PR', '42' => 'SC', '43' => 'RS', '50' => 'MS', '51' => 'MT',
15
+ '52' => 'GO', '53' => 'DF'
16
+ }.freeze
17
+
18
+ def execute(xml)
19
+ {
20
+ company_name: locate_element(xml, 'infCFe/emit/xNome'),
21
+ address: company_address_params(xml),
22
+ trading_name: locate_element(xml, 'infCFe/emit/xFant'),
23
+ zipcode: locate_element(xml, 'infCFe/emit/enderEmit/CEP'),
24
+ cnpj: locate_element(xml, 'infCFe/ide/CNPJ'),
25
+ ie: locate_element(xml, 'infCFe/emit/IE'),
26
+ im: locate_element(xml, 'infCFe/emit/IM')
27
+ }
28
+ end
29
+
30
+ def company_address_params(xml)
31
+ {
32
+ public_place: locate_element(xml, 'infCFe/emit/enderEmit/xLgr'),
33
+ number: locate_element(xml, 'infCFe/emit/enderEmit/nro'),
34
+ complement: locate_element(xml, 'infCFe/emit/enderEmit/xCpl'),
35
+ city: locate_element(xml, 'infCFe/emit/enderEmit/xMun'),
36
+ neighborhood: locate_element(xml, 'infCFe/emit/enderEmit/xBairro'),
37
+ cep: locate_element(xml, 'infCFe/emit/enderEmit/CEP'),
38
+ state: SEFAZ_STATE_CODES[locate_element(xml, 'infCFe/ide/cUF')]
39
+ }
40
+ end
41
+ private_class_method :company_address_params
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,15 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module Cpf
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ def execute(xml)
10
+ locate_element(xml, 'infCFe/dest/CPF')
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module DocumentNumber
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ def execute(xml)
10
+ locate_element(xml, 'infCFe/ide/nCFe')
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module FiscoObs
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ def execute(xml)
10
+ xml.locate('infCFe/infAdic/obsFisco').map do |element|
11
+ node = element.nodes.first
12
+ field = element.attributes[:xCampo]
13
+ next unless node && field
14
+ {
15
+ text: node.text,
16
+ field: field
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module Payment
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ def execute(xml)
10
+ {
11
+ approximate_value_of_taxes: locate_element(xml, 'infCFe/total/vCFeLei12741'),
12
+ total: locate_element(xml, 'infCFe/total/vCFe'),
13
+ discount: locate_element(xml, 'infCFe/total/ICMSTot/vDesc'),
14
+ total_price: locate_element(xml, 'infCFe/total/ICMSTot/vProd'),
15
+ cashback: locate_element(xml, 'infCFe/pgto/vTroco'),
16
+ paid: locate_element(xml, 'infCFe/pgto/MP/vMP')
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module Payments
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ PAYMENT_TYPES = {
10
+ '01' => 'Dinheiro',
11
+ '02' => 'Cheque',
12
+ '03' => 'Cartão de Crédito',
13
+ '04' => 'Cartão de Débito',
14
+ '05' => 'Crédito Loja',
15
+ '10' => 'Vale Alimentação',
16
+ '11' => 'Vale Refeição',
17
+ '12' => 'Vale Presente',
18
+ '13' => 'Vale Combustível',
19
+ '99' => 'Outros'
20
+ }.freeze
21
+
22
+ def execute(xml)
23
+ node_payments = xml.locate('infCFe/pgto')
24
+
25
+ payments_by_nodes(node_payments) if node_payments && node_payments.any?
26
+ end
27
+
28
+ def payments_by_nodes(node_payments)
29
+ node_payments.first.nodes
30
+ .select { |element| element.value == 'MP' }
31
+ .map { |element| payment_by(element) }
32
+ end
33
+ private_class_method :payments_by_nodes
34
+
35
+ def payment_by(element)
36
+ {
37
+ type: PAYMENT_TYPES[locate_element(element, 'cMP')],
38
+ amount: locate_element(element, 'vMP')
39
+ }
40
+ end
41
+ private_class_method :payment_by
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,37 @@
1
+ module BrInvoicesPdf
2
+ module Cfe
3
+ module Parser
4
+ module ProductsData
5
+ extend BaseParser
6
+
7
+ module_function
8
+
9
+ FIELDS = { code: 'cProd',
10
+ description: 'xProd',
11
+ cfop: 'CFOP',
12
+ quantity: 'qCom',
13
+ unit_label: 'uCom',
14
+ total_value: 'vProd',
15
+ unit_value: 'vUnCom',
16
+ item_value: 'vItem' }.freeze
17
+
18
+ def execute(xml)
19
+ node_products = xml.locate('infCFe/det')
20
+ products_params(node_products) if node_products
21
+ end
22
+
23
+ def products_params(node_products)
24
+ node_products.map(&method(:product_by))
25
+ end
26
+ private_class_method :products_params
27
+
28
+ def product_by(element)
29
+ FIELDS
30
+ .map { |(key, field)| [key, node_locate(element, field)] }
31
+ .to_h
32
+ end
33
+ private_class_method :product_by
34
+ end
35
+ end
36
+ end
37
+ end