sefaz 0.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +121 -0
  4. data/Gemfile.lock +77 -20
  5. data/README.md +449 -17
  6. data/Rakefile +1 -0
  7. data/docs/CFe-SAT/Especificacao_SAT_v_ER_2_30_03.pdf +0 -0
  8. data/docs/CFe-SAT/Manual_Orientacao_SAT_v_MO_2_19_04.pdf +0 -0
  9. data/docs/CFe-SAT/Manual_do_Emulador_SAT-CF-e_Offline_2015_09_10.pdf +0 -0
  10. data/docs/CFe-SAT/_CANCEL_dataset.md +14 -0
  11. data/docs/CFe-SAT/_SALE_dataset.md +171 -0
  12. data/docs/CFe-SAT/emulador_off_line_v2_9_4.zip +0 -0
  13. data/docs/NFe-NFCe/ANEXO I - Leiaute e Regra de Valida/303/247/303/243o - NF-e e NFC-e.pdf +0 -0
  14. data/docs/NFe-NFCe/ANEXO II -Manual Especifica/303/247/303/265esT/303/251cnicas - Danfe-C/303/263digo-Barras.pdf +0 -0
  15. data/docs/NFe-NFCe/Anexo III - Manual de Conting/303/252ncia - NF-e.pdf +0 -0
  16. data/docs/NFe-NFCe/Anexo IV - Manual de Conting/303/252ncia - NFC-e.pdf +0 -0
  17. data/docs/NFe-NFCe/Manual de Orienta/303/247/303/243o ao Contribuinte - MOC - vers/303/243o 7.0 - NF-e e NFC-e.pdf +0 -0
  18. data/docs/NFe-NFCe/_dataset.md +819 -0
  19. data/lib/sefaz/assets/NFe_logo.png +0 -0
  20. data/lib/sefaz/base.rb +11 -0
  21. data/lib/sefaz/configuration.rb +66 -0
  22. data/lib/sefaz/exception.rb +14 -0
  23. data/lib/sefaz/refinement.rb +91 -0
  24. data/lib/sefaz/utils/connection.rb +35 -0
  25. data/lib/sefaz/utils/prawn_helper.rb +49 -0
  26. data/lib/sefaz/utils/signer.rb +122 -0
  27. data/lib/sefaz/version.rb +1 -1
  28. data/lib/sefaz/webservice/base.rb +13 -0
  29. data/lib/sefaz/webservice/nfe/auditor.rb +35 -0
  30. data/lib/sefaz/webservice/nfe/client.rb +471 -0
  31. data/lib/sefaz/webservice/nfe/connection.rb +17 -0
  32. data/lib/sefaz/webservice/nfe/dataset.rb +451 -0
  33. data/lib/sefaz/webservice/nfe/templates/base.rb +32 -0
  34. data/lib/sefaz/webservice/nfe/templates/evento_cancelamento.rb +48 -0
  35. data/lib/sefaz/webservice/nfe/templates/evento_carta_correcao.rb +54 -0
  36. data/lib/sefaz/webservice/nfe/templates/evento_inutilizacao.rb +22 -0
  37. data/lib/sefaz/webservice/nfe/validator.rb +63 -0
  38. data/lib/sefaz/webservice/nfe/wsdl.rb +117 -0
  39. data/lib/sefaz/webservice/sat/client.rb +44 -0
  40. data/lib/sefaz/webservice/sat/dataset/cancel.rb +34 -0
  41. data/lib/sefaz/webservice/sat/dataset/sale.rb +176 -0
  42. data/lib/sefaz/webservice/sat/templates/base.rb +54 -0
  43. data/lib/sefaz/webservice/sat/templates/cupom_fiscal_55mm.rb +307 -0
  44. data/lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb +307 -0
  45. data/lib/sefaz.rb +51 -3
  46. data/sefaz.gemspec +6 -3
  47. metadata +103 -9
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module NFE
6
+ # Validador de XML pelo validador público da SEFAZ-RS
7
+ class Validator
8
+
9
+ def initialize(xml)
10
+ @xml = xml
11
+ end
12
+
13
+ def exec(openTimeout, readTimeout)
14
+ uri = URI("https://www.sefaz.rs.gov.br/NFE/NFE-VAL.aspx")
15
+ http = Net::HTTP.new(uri.host, uri.port)
16
+ http.use_ssl = true
17
+ http.open_timeout = openTimeout
18
+ http.read_timeout = readTimeout
19
+ content = Net::HTTP::Post.new(uri.request_uri)
20
+ content.set_form_data(txtxml: @xml)
21
+ response = http.request(content)
22
+ if response.code == "200"
23
+ nodes = Nokogiri::HTML(response.body.force_encoding('utf-8')).css('.tabela_resultado li').to_a
24
+ mensagens = {}
25
+ falhas = {}
26
+ nodes[0..2].each do |node|
27
+ k = get_key(node)
28
+ v = get_message(node)
29
+ mensagens[k] = v
30
+ falhas[k] = v if node.to_s.include?('../Imagens/erro.png')
31
+ end
32
+ return [:ok, mensagens, falhas]
33
+ end
34
+ return [:error, {}, {}]
35
+ end
36
+
37
+ private
38
+
39
+ def get_key(node)
40
+ if node.elements[0].to_s.include?('<a href=')
41
+ "Schema XML"
42
+ else
43
+ node.elements[1].text.to_s.delete(':').strip
44
+ end
45
+ end
46
+
47
+ def get_message(node)
48
+ if node.elements[0].to_s.include?('<a href=')
49
+ contents = []
50
+ node.elements[1].elements.each do |el|
51
+ contents.push(el.text.to_s.strip)
52
+ end
53
+ return contents
54
+ else
55
+ key = node.elements[1].text.to_s
56
+ return [node.text.to_s.sub(key, '').strip]
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module NFE
6
+ # Módulo que contém todos os WSDL do módulo NF-e/NFC-e
7
+ module WSDL
8
+
9
+ # Ambiente: 1=Produção; 2=Homologação
10
+ # Operações:
11
+ # - :NfeInutilizacao - OK (enviarInutilizarNF)
12
+ # - :NfeConsultaProtocolo - OK (consultarNF)
13
+ # - :NfeStatusServico - OK (statusDoServico)
14
+ # - :NfeConsultaCadastro - OK (consultarCadastro)
15
+ # - :RecepcaoEvento - OK (enviarLoteDeEvento)
16
+ # - :NFeAutorizacao - OK (enviarLoteNF)
17
+ # - :NFeRetAutorizacao - OK (consultarRecibo)
18
+ # UF: código IBGE do Estado
19
+
20
+ # Método retorna a URL wsdl da SEFAZ, exemplo de consumo:
21
+ # @wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NfeStatusServico, "1", "35")
22
+
23
+ def self.get(operacao, ambiente, uf)
24
+ case uf.to_s
25
+ when "13"; SEFAZ::Webservice::NFE::WSDL.wsdl_am(ambiente.to_s)[operacao.to_sym] # Sefaz Amazonas - (AM)
26
+ when "29"; SEFAZ::Webservice::NFE::WSDL.wsdl_ba(ambiente.to_s)[operacao.to_sym] # Sefaz Bahia - (BA)
27
+ # when "52"; SEFAZ::Webservice::NFE::WSDL.wsdl_go(ambiente.to_s)[operacao.to_sym] # Sefaz Goias - (GO)
28
+ # when "31"; SEFAZ::Webservice::NFE::WSDL.wsdl_mg(ambiente.to_s)[operacao.to_sym] # Sefaz Minas Gerais - (MG)
29
+ # when "50"; SEFAZ::Webservice::NFE::WSDL.wsdl_ms(ambiente.to_s)[operacao.to_sym] # Sefaz Mato Grosso do Sul - (MS)
30
+ # when "51"; SEFAZ::Webservice::NFE::WSDL.wsdl_mt(ambiente.to_s)[operacao.to_sym] # Sefaz Mato Grosso - (MT)
31
+ # when "26"; SEFAZ::Webservice::NFE::WSDL.wsdl_pe(ambiente.to_s)[operacao.to_sym] # Sefaz Pernambuco - (PE)
32
+ # when "41"; SEFAZ::Webservice::NFE::WSDL.wsdl_pr(ambiente.to_s)[operacao.to_sym] # Sefaz Paraná - (PR)
33
+ # when "43"; SEFAZ::Webservice::NFE::WSDL.wsdl_rs(ambiente.to_s)[operacao.to_sym] # Sefaz Rio Grande do Sul - (RS)
34
+ when "35"; SEFAZ::Webservice::NFE::WSDL.wsdl_sp(ambiente.to_s)[operacao.to_sym] # Sefaz São Paulo - (SP)
35
+ end
36
+ end
37
+
38
+ # Sefaz Amazonas - (AM)
39
+ def self.wsdl_am(ambiente)
40
+ case ambiente
41
+ when "1"
42
+ {
43
+ NfeInutilizacao: "https://nfe.sefaz.am.gov.br/services2/services/NfeInutilizacao4?wsdl",
44
+ NfeConsultaProtocolo: "https://nfe.sefaz.am.gov.br/services2/services/NfeConsulta4?wsdl",
45
+ NfeStatusServico: "https://nfe.sefaz.am.gov.br/services2/services/NfeStatusServico4?wsdl",
46
+ RecepcaoEvento: "https://nfe.sefaz.am.gov.br/services2/services/RecepcaoEvento4?wsdl",
47
+ NFeAutorizacao: "https://nfe.sefaz.am.gov.br/services2/services/NfeAutorizacao4?wsdl",
48
+ NFeRetAutorizacao: "https://nfe.sefaz.am.gov.br/services2/services/NfeRetAutorizacao4?wsdl"
49
+ }
50
+ when "2"
51
+ {
52
+ NfeInutilizacao: "https://homnfe.sefaz.am.gov.br/services2/services/NfeInutilizacao4?wsdl",
53
+ NfeConsultaProtocolo: "https://homnfe.sefaz.am.gov.br/services2/services/NfeConsulta4?wsdl",
54
+ NfeStatusServico: "https://homnfe.sefaz.am.gov.br/services2/services/NfeStatusServico4?wsdl",
55
+ RecepcaoEvento: "https://homnfe.sefaz.am.gov.br/services2/services/RecepcaoEvento4?wsdl",
56
+ NFeAutorizacao: "https://homnfe.sefaz.am.gov.br/services2/services/NfeAutorizacao4?wsdl",
57
+ NFeRetAutorizacao: "https://homnfe.sefaz.am.gov.br/services2/services/NfeRetAutorizacao4?wsdl"
58
+ }
59
+ end
60
+ end
61
+
62
+ # Sefaz Bahia - (BA)
63
+ def self.wsdl_ba(ambiente)
64
+ case ambiente
65
+ when "1"
66
+ {
67
+ NfeInutilizacao: "https://nfe.sefaz.ba.gov.br/webservices/NFeInutilizacao4/NFeInutilizacao4.asmx?wsdl",
68
+ NfeConsultaProtocolo: "https://nfe.sefaz.ba.gov.br/webservices/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx?wsdl",
69
+ NfeStatusServico: "https://nfe.sefaz.ba.gov.br/webservices/NFeStatusServico4/NFeStatusServico4.asmx?wsdl",
70
+ NfeConsultaCadastro: "https://nfe.sefaz.ba.gov.br/webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx?wsdl",
71
+ RecepcaoEvento: "https://nfe.sefaz.ba.gov.br/webservices/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?wsdl",
72
+ NFeAutorizacao: "https://nfe.sefaz.ba.gov.br/webservices/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl",
73
+ NFeRetAutorizacao: "https://nfe.sefaz.ba.gov.br/webservices/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx?wsdl"
74
+ }
75
+ when "2"
76
+ {
77
+ NfeInutilizacao: "https://hnfe.sefaz.ba.gov.br/webservices/NFeInutilizacao4/NFeInutilizacao4.asmx?wsdl",
78
+ NfeConsultaProtocolo: "https://hnfe.sefaz.ba.gov.br/webservices/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx?wsdl",
79
+ NfeStatusServico: "https://hnfe.sefaz.ba.gov.br/webservices/NFeStatusServico4/NFeStatusServico4.asmx?wsdl",
80
+ NfeConsultaCadastro: "https://hnfe.sefaz.ba.gov.br/webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx?wsdl",
81
+ RecepcaoEvento: "https://hnfe.sefaz.ba.gov.br/webservices/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?wsdl",
82
+ NFeAutorizacao: "https://hnfe.sefaz.ba.gov.br/webservices/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl",
83
+ NFeRetAutorizacao: "https://hnfe.sefaz.ba.gov.br/webservices/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx?wsdl"
84
+ }
85
+ end
86
+ end
87
+
88
+ # Sefaz São Paulo - (SP)
89
+ def self.wsdl_sp(ambiente)
90
+ case ambiente
91
+ when "1"
92
+ {
93
+ NfeInutilizacao: "https://nfe.fazenda.sp.gov.br/ws/nfeinutilizacao4.asmx?wsdl",
94
+ NfeConsultaProtocolo: "https://nfe.fazenda.sp.gov.br/ws/nfeconsultaprotocolo4.asmx?wsdl",
95
+ NfeStatusServico: "https://nfe.fazenda.sp.gov.br/ws/nfestatusservico4.asmx?wsdl",
96
+ NfeConsultaCadastro: "https://nfe.fazenda.sp.gov.br/ws/cadconsultacadastro4.asmx?wsdl",
97
+ RecepcaoEvento: "https://nfe.fazenda.sp.gov.br/ws/nferecepcaoevento4.asmx?wsdl",
98
+ NFeAutorizacao: "https://nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx?wsdl",
99
+ NFeRetAutorizacao: "https://nfe.fazenda.sp.gov.br/ws/nferetautorizacao4.asmx?wsdl"
100
+ }
101
+ when "2"
102
+ {
103
+ NfeInutilizacao: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nfeinutilizacao4.asmx?wsdl",
104
+ NfeConsultaProtocolo: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nfeconsultaprotocolo4.asmx?wsdl",
105
+ NfeStatusServico: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nfestatusservico4.asmx?wsdl",
106
+ NfeConsultaCadastro: "https://homologacao.nfe.fazenda.sp.gov.br/ws/cadconsultacadastro4.asmx?wsdl",
107
+ RecepcaoEvento: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nferecepcaoevento4.asmx?wsdl",
108
+ NFeAutorizacao: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx?wsdl",
109
+ NFeRetAutorizacao: "https://homologacao.nfe.fazenda.sp.gov.br/ws/nferetautorizacao4.asmx?wsdl"
110
+ }
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module SAT
6
+ # Principal classe de integração com o módulo CFe-SAT
7
+ class Client < SEFAZ::Webservice::Base
8
+
9
+ SERVICES = %i[ exportarCF ]
10
+
11
+ def initialize
12
+ end
13
+
14
+ # Exportar CFe (Cupom Fiscal Eletrônico) no formato PDF
15
+ # Para gerar o CFe de Cancelamento, é obrigatório informar o @canc (CFe de Cancelmaneto) junto com o @aut (CFe de Movimento)
16
+ #
17
+ # Exemplo de CFe de Movimento:
18
+ # @pdf = @client.exportarCF(80, aut: @aut, infAdic: "Participe da Promoção de Natal.")
19
+ #
20
+ # Exemplo de CFe de Cancelmaneto:
21
+ # @pdf = @client.exportarCF(80, aut: @aut, canc: @canc, infAdic: "Participe da Promoção de Natal.")
22
+ #
23
+ # @mm(Integer) = Milímetro da bobina termica para gerar o documento PDF (opções=55,80)
24
+ # @aut(Hash ou String) = XML ou Hash - Autorizado
25
+ # @canc(Hash ou String) = XML ou Hash - Cancelamento (OPCIONAL)
26
+ # @summary(Boolean) = Exibir Extrato de Movimento no formato resumido (OPCIONAL)
27
+ # @infAdic(String) = Informações adicionais de rodapé do CFe (OPCIONAL)
28
+ def exportarCF(mm, aut:, canc: nil, summary: false, infAdic: nil)
29
+ aut = (aut.is_a?(Hash) ? aut : aut.to_hash!)
30
+ canc = (canc.is_a?(Hash) ? canc : canc.to_hash!) if canc
31
+ case mm
32
+ when 55
33
+ SEFAZ::Webservice::SAT::Templates::CupomFiscal55mm.new.render(aut, canc, summary, infAdic)
34
+ when 80
35
+ SEFAZ::Webservice::SAT::Templates::CupomFiscal80mm.new.render(aut, canc, summary, infAdic)
36
+ else
37
+ SEFAZ::Webservice::SAT::Templates::Base.new.render(aut, canc, summary, infAdic)
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module SAT
6
+ module Dataset
7
+ # Principal classe de elaboração do XML de Cancelamento para o módulo CFe-SAT
8
+ class Cancel
9
+
10
+ attr_accessor :ide
11
+
12
+ IDE = Struct.new(:CNPJ, :signAC, :numeroCaixa)
13
+
14
+ def initialize(chCanc)
15
+ @chCanc = chCanc
16
+ @ide = IDE.new
17
+ end
18
+
19
+ def gerarCF
20
+ hash = { CFeCanc: { infCFe: { :@chCanc => ("CFe" + @chCanc.to_s) } } }
21
+ hash[:CFeCanc][:infCFe][:ide] = @ide.to_h
22
+ hash[:CFeCanc][:infCFe][:emit] = {}
23
+ hash[:CFeCanc][:infCFe][:dest] = {}
24
+ hash[:CFeCanc][:infCFe][:total] = {}
25
+ hash[:CFeCanc][:infCFe][:infAdic] = {}
26
+
27
+ return [hash.to_xml!, hash]
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module SAT
6
+ module Dataset
7
+ # Principal classe de elaboração do XML de Venda para o módulo CFe-SAT
8
+ class Sale
9
+
10
+ attr_accessor :ide, :emit, :dest, :entrega, :det, :obsfiscodet, :total, :pgto, :mp, :infAdic
11
+
12
+ IDE = Struct.new(:CNPJ, :signAC, :numeroCaixa)
13
+ EMIT = Struct.new(:CNPJ, :IE, :IM, :cRegTribISSQN, :indRatISSQN)
14
+ DEST = Struct.new(:CNPJ, :CPF, :xNome)
15
+ ENTREGA = Struct.new(:xLgr, :nro, :xCpl, :xBairro, :xMun, :UF)
16
+ DET = Struct.new(:@nItem, :prod, :imposto, :infAdProd)
17
+ PROD = Struct.new(:cProd, :cEAN, :xProd, :NCM, :CEST, :CFOP, :uCom, :qCom, :vUnCom, :indRegra, :vDesc, :vOutro, :obsFiscoDet, :cANP)
18
+ OBSFISCODET = Struct.new(:xCampoDet, :xTextoDet)
19
+ IMPOSTO = Struct.new(:vItem12741, :ICMS, :PIS, :PISST, :COFINS, :COFINSST, :ISSQN)
20
+ ICMS = Struct.new(:ICMS00, :ICMS40, :ICMSSN102, :ICMSSN900)
21
+ ICMS00 = Struct.new(:Orig, :CST, :pICMS)
22
+ ICMS40 = Struct.new(:Orig, :CST)
23
+ ICMSSN102 = Struct.new(:Orig, :CSOSN)
24
+ ICMSSN900 = Struct.new(:Orig, :CSOSN, :pICMS)
25
+ PIS = Struct.new(:PISAliq, :PISQtde, :PISNT, :PISSN, :PISOutr)
26
+ PISAliq = Struct.new(:CST, :vBC, :pPIS)
27
+ PISQtde = Struct.new(:CST, :qBCProd, :vAliqProd)
28
+ PISNT = Struct.new(:CST)
29
+ PISSN = Struct.new(:CST)
30
+ PISOutr = Struct.new(:CST, :vBC, :pPIS, :qBCProd, :vAliqProd)
31
+ PISST = Struct.new(:vBC, :pPIS, :qBCProd, :vAliqProd)
32
+ COFINS = Struct.new(:COFINSAliq, :COFINSQtde, :COFINSNT, :COFINSSN, :COFINSOutr)
33
+ COFINSAliq = Struct.new(:CST, :vBC, :pCOFINS)
34
+ COFINSQtde = Struct.new(:CST, :qBCProd, :vAliqProd)
35
+ COFINSNT = Struct.new(:CST)
36
+ COFINSSN = Struct.new(:CST)
37
+ COFINSOutr = Struct.new(:CST, :vBC, :pCOFINS, :qBCProd, :vAliqProd)
38
+ COFINSST = Struct.new(:vBC, :pCOFINS, :qBCProd, :vAliqProd)
39
+ ISSQN = Struct.new(:vDeducISSQN, :vAliq, :cMunFG, :cListServ, :cServTribMun, :cNatOp, :indIncFisc)
40
+ TOTAL = Struct.new(:DescAcrEntr, :vCFeLei12741)
41
+ DescAcrEntr = Struct.new(:vDescSubtot, :vAcresSubtot)
42
+ PGTO = Struct.new(:MP)
43
+ MP = Struct.new(:cMP, :vMP, :cAdmC, :cAut)
44
+ INFADIC = Struct.new(:infCpl)
45
+
46
+ def initialize
47
+ @versaoDadosEnt = "0.08"
48
+
49
+ @ide = IDE.new
50
+ @emit = EMIT.new
51
+ @dest = DEST.new
52
+ @entrega = ENTREGA.new
53
+ @total = TOTAL.new
54
+ @total.DescAcrEntr = DescAcrEntr.new
55
+ @pgto = PGTO.new
56
+ @pgto.MP = []
57
+ @infAdic = INFADIC.new
58
+
59
+ @listas = {}
60
+ @listas[:det] = []
61
+ end
62
+
63
+ def gerarCF
64
+ # Raiz = CFe
65
+ # A01 = infCFe
66
+ # H01 = det
67
+ # I01 = prod
68
+ # M01 = imposto
69
+ # N01 = ICMS
70
+ hash = { CFe: { infCFe: { :@versaoDadosEnt => @versaoDadosEnt } } }
71
+ hash[:CFe][:infCFe][:ide] = @ide.to_h
72
+ hash[:CFe][:infCFe][:emit] = @emit.to_h
73
+ hash[:CFe][:infCFe][:dest] = @dest.to_h
74
+ hash[:CFe][:infCFe][:entrega] = @entrega.to_h
75
+ hash[:CFe][:infCFe][:det] = @listas[:det]
76
+ hash[:CFe][:infCFe][:total] = @total.to_h
77
+ hash[:CFe][:infCFe][:total][:DescAcrEntr] = @total.DescAcrEntr.to_h
78
+ hash[:CFe][:infCFe][:pgto] = @pgto.to_h
79
+ hash[:CFe][:infCFe][:infAdic] = @infAdic.to_h
80
+ compressed = hash.compress!
81
+
82
+ return [compressed.to_xml!, compressed]
83
+ end
84
+
85
+ def add(part_name)
86
+ part_object = case part_name
87
+ when "DET"
88
+ @det = DET.new
89
+ @det.prod = PROD.new
90
+ @det.prod.obsFiscoDet = []
91
+ @det.imposto = IMPOSTO.new
92
+ @det.imposto.ICMS = ICMS.new
93
+ @det.imposto.ICMS.ICMS00 = ICMS00.new
94
+ @det.imposto.ICMS.ICMS40 = ICMS40.new
95
+ @det.imposto.ICMS.ICMSSN102 = ICMSSN102.new
96
+ @det.imposto.ICMS.ICMSSN900 = ICMSSN900.new
97
+ @det.imposto.PIS = PIS.new
98
+ @det.imposto.PIS.PISAliq = PISAliq.new
99
+ @det.imposto.PIS.PISQtde = PISQtde.new
100
+ @det.imposto.PIS.PISNT = PISNT.new
101
+ @det.imposto.PIS.PISSN = PISSN.new
102
+ @det.imposto.PIS.PISOutr = PISOutr.new
103
+ @det.imposto.PISST = PISST.new
104
+ @det.imposto.COFINS = COFINS.new
105
+ @det.imposto.COFINS.COFINSAliq = COFINSAliq.new
106
+ @det.imposto.COFINS.COFINSQtde = COFINSQtde.new
107
+ @det.imposto.COFINS.COFINSNT = COFINSNT.new
108
+ @det.imposto.COFINS.COFINSSN = COFINSSN.new
109
+ @det.imposto.COFINS.COFINSOutr = COFINSOutr.new
110
+ @det.imposto.COFINSST = COFINSST.new
111
+ @det.imposto.ISSQN = ISSQN.new
112
+ @det
113
+ when "OBSFISCODET"
114
+ @obsfiscodet = OBSFISCODET.new
115
+ @obsfiscodet
116
+ when "MP"
117
+ @mp = MP.new
118
+ @mp
119
+ end
120
+
121
+ if block_given?
122
+ yield(part_object)
123
+ save(part_name)
124
+ end
125
+
126
+ nil
127
+ end
128
+
129
+ def save(part_name)
130
+ case part_name
131
+ when "DET"
132
+ if @det.is_a?(DET)
133
+ item = @det
134
+ item.prod = item.prod.to_h
135
+ item.imposto.ICMS.ICMS00 = item.imposto.ICMS.ICMS00.to_h
136
+ item.imposto.ICMS.ICMS40 = item.imposto.ICMS.ICMS40.to_h
137
+ item.imposto.ICMS.ICMSSN102 = item.imposto.ICMS.ICMSSN102.to_h
138
+ item.imposto.ICMS.ICMSSN900 = item.imposto.ICMS.ICMSSN900.to_h
139
+ item.imposto.ICMS = item.imposto.ICMS.to_h
140
+ item.imposto.PIS.PISAliq = item.imposto.PIS.PISAliq.to_h
141
+ item.imposto.PIS.PISQtde = item.imposto.PIS.PISQtde.to_h
142
+ item.imposto.PIS.PISNT = item.imposto.PIS.PISNT.to_h
143
+ item.imposto.PIS.PISSN = item.imposto.PIS.PISSN.to_h
144
+ item.imposto.PIS.PISOutr = item.imposto.PIS.PISOutr.to_h
145
+ item.imposto.PIS = item.imposto.PIS.to_h
146
+ item.imposto.PISST = item.imposto.PISST.to_h
147
+ item.imposto.COFINS.COFINSAliq = item.imposto.COFINS.COFINSAliq.to_h
148
+ item.imposto.COFINS.COFINSQtde = item.imposto.COFINS.COFINSQtde.to_h
149
+ item.imposto.COFINS.COFINSNT = item.imposto.COFINS.COFINSNT.to_h
150
+ item.imposto.COFINS.COFINSSN = item.imposto.COFINS.COFINSSN.to_h
151
+ item.imposto.COFINS.COFINSOutr = item.imposto.COFINS.COFINSOutr.to_h
152
+ item.imposto.COFINS = item.imposto.COFINS.to_h
153
+ item.imposto.COFINSST = item.imposto.COFINSST.to_h
154
+ item.imposto.ISSQN = item.imposto.ISSQN.to_h
155
+ item.imposto = item.imposto.to_h
156
+ item[:@nItem] = (@listas[:det].length + 1)
157
+ @listas[:det].push(item.to_h)
158
+ end
159
+ when "OBSFISCODET"
160
+ if @det.is_a?(DET) && @obsfiscodet.is_a?(OBSFISCODET)
161
+ @det.prod.obsFiscoDet.push(@obsfiscodet.to_h)
162
+ end
163
+ when "MP"
164
+ if @pgto.is_a?(PGTO) && @mp.is_a?(MP)
165
+ @pgto.MP.push(@mp.to_h)
166
+ end
167
+ end
168
+
169
+ nil
170
+ end
171
+
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module SAT
6
+ module Templates
7
+ # Classe base dos templates para CFe-SAT
8
+ class Base
9
+
10
+ include SEFAZ::Utils::PrawnHelper
11
+
12
+ def initialize
13
+ @page_width = 0
14
+ @margin = 0
15
+ @page_break = 80.m
16
+ @page_layout = :portrait
17
+ end
18
+
19
+ def build(doc, aut, canc, summary, infAdic)
20
+ raise SEFAZ::NotImplemented, "Você deve implementar o método 'build' em uma subclasse."
21
+ end
22
+
23
+ def render(aut, canc, summary, infAdic)
24
+ validation(aut, canc)
25
+
26
+ Prawn::Document.new(page_size: [@page_width, @page_break], margin: @margin, page_layout: @page_layout) do |doc|
27
+ build(doc, aut, canc, summary, infAdic)
28
+ doc.page.dictionary.data[:MediaBox] = [0, (doc.y - @margin), @page_width, @page_break]
29
+ end.render
30
+ end
31
+
32
+ private
33
+
34
+ def validation(aut, canc)
35
+ unless aut.is_a?(Hash) && aut.dig(:CFe, :Signature) && aut.dig(:CFe, :infCFe, :@Id) &&
36
+ aut.dig(:CFe, :infCFe, :ide) && aut.dig(:CFe, :infCFe, :emit) && aut.dig(:CFe, :infCFe, :emit, :enderEmit) &&
37
+ aut.dig(:CFe, :infCFe, :det) && aut.dig(:CFe, :infCFe, :total) && aut.dig(:CFe, :infCFe, :pgto)
38
+ raise SEFAZ::ValidationError, "Layout do arquivo CFe-SAT inválido (Tipo de Arquivo: AUTORIZADO)."
39
+ end
40
+
41
+ if canc
42
+ unless canc.is_a?(Hash) && canc.dig(:CFeCanc, :Signature) && canc.dig(:CFeCanc, :infCFe, :@Id) && canc.dig(:CFeCanc, :infCFe, :@chCanc) &&
43
+ canc.dig(:CFeCanc, :infCFe, :ide) && canc.dig(:CFeCanc, :infCFe, :emit) && canc.dig(:CFeCanc, :infCFe, :emit, :enderEmit) &&
44
+ canc.dig(:CFeCanc, :infCFe, :total) && (aut.dig(:CFe, :infCFe, :@Id) == canc.dig(:CFeCanc, :infCFe, :@chCanc))
45
+ raise SEFAZ::ValidationError, "Layout do arquivo CFe-SAT inválido (Tipo de Arquivo: CANCELAMENTO)."
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end