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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/CHANGELOG.md +121 -0
- data/Gemfile.lock +77 -20
- data/README.md +449 -17
- data/Rakefile +1 -0
- data/docs/CFe-SAT/Especificacao_SAT_v_ER_2_30_03.pdf +0 -0
- data/docs/CFe-SAT/Manual_Orientacao_SAT_v_MO_2_19_04.pdf +0 -0
- data/docs/CFe-SAT/Manual_do_Emulador_SAT-CF-e_Offline_2015_09_10.pdf +0 -0
- data/docs/CFe-SAT/_CANCEL_dataset.md +14 -0
- data/docs/CFe-SAT/_SALE_dataset.md +171 -0
- data/docs/CFe-SAT/emulador_off_line_v2_9_4.zip +0 -0
- data/docs/NFe-NFCe/ANEXO I - Leiaute e Regra de Valida/303/247/303/243o - NF-e e NFC-e.pdf +0 -0
- data/docs/NFe-NFCe/ANEXO II -Manual Especifica/303/247/303/265esT/303/251cnicas - Danfe-C/303/263digo-Barras.pdf +0 -0
- data/docs/NFe-NFCe/Anexo III - Manual de Conting/303/252ncia - NF-e.pdf +0 -0
- data/docs/NFe-NFCe/Anexo IV - Manual de Conting/303/252ncia - NFC-e.pdf +0 -0
- 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
- data/docs/NFe-NFCe/_dataset.md +819 -0
- data/lib/sefaz/assets/NFe_logo.png +0 -0
- data/lib/sefaz/base.rb +11 -0
- data/lib/sefaz/configuration.rb +66 -0
- data/lib/sefaz/exception.rb +14 -0
- data/lib/sefaz/refinement.rb +91 -0
- data/lib/sefaz/utils/connection.rb +35 -0
- data/lib/sefaz/utils/prawn_helper.rb +49 -0
- data/lib/sefaz/utils/signer.rb +122 -0
- data/lib/sefaz/version.rb +1 -1
- data/lib/sefaz/webservice/base.rb +13 -0
- data/lib/sefaz/webservice/nfe/auditor.rb +35 -0
- data/lib/sefaz/webservice/nfe/client.rb +471 -0
- data/lib/sefaz/webservice/nfe/connection.rb +17 -0
- data/lib/sefaz/webservice/nfe/dataset.rb +451 -0
- data/lib/sefaz/webservice/nfe/templates/base.rb +32 -0
- data/lib/sefaz/webservice/nfe/templates/evento_cancelamento.rb +48 -0
- data/lib/sefaz/webservice/nfe/templates/evento_carta_correcao.rb +54 -0
- data/lib/sefaz/webservice/nfe/templates/evento_inutilizacao.rb +22 -0
- data/lib/sefaz/webservice/nfe/validator.rb +63 -0
- data/lib/sefaz/webservice/nfe/wsdl.rb +117 -0
- data/lib/sefaz/webservice/sat/client.rb +44 -0
- data/lib/sefaz/webservice/sat/dataset/cancel.rb +34 -0
- data/lib/sefaz/webservice/sat/dataset/sale.rb +176 -0
- data/lib/sefaz/webservice/sat/templates/base.rb +54 -0
- data/lib/sefaz/webservice/sat/templates/cupom_fiscal_55mm.rb +307 -0
- data/lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb +307 -0
- data/lib/sefaz.rb +51 -3
- data/sefaz.gemspec +6 -3
- 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
|