br_nfe 1.0.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 +7 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +169 -0
- data/LICENSE +20 -0
- data/README.markdown +6 -0
- data/Rakefile +13 -0
- data/br_nfe.gemspec +28 -0
- data/lib/br_nfe/active_model_base.rb +62 -0
- data/lib/br_nfe/base.rb +168 -0
- data/lib/br_nfe/condicao_pagamento.rb +26 -0
- data/lib/br_nfe/destinatario.rb +26 -0
- data/lib/br_nfe/emitente.rb +40 -0
- data/lib/br_nfe/endereco.rb +44 -0
- data/lib/br_nfe/helper/cpf_cnpj.rb +60 -0
- data/lib/br_nfe/helper/have_address.rb +29 -0
- data/lib/br_nfe/helper/have_condicao_pagamento.rb +24 -0
- data/lib/br_nfe/helper/have_destinatario.rb +18 -0
- data/lib/br_nfe/helper/have_emitente.rb +20 -0
- data/lib/br_nfe/helper/have_intermediario.rb +24 -0
- data/lib/br_nfe/helper/have_rps.rb +27 -0
- data/lib/br_nfe/helper/string_methods.rb +21 -0
- data/lib/br_nfe/seed.rb +195 -0
- data/lib/br_nfe/servico/base.rb +35 -0
- data/lib/br_nfe/servico/betha/base.rb +74 -0
- data/lib/br_nfe/servico/betha/v1/build_response.rb +219 -0
- data/lib/br_nfe/servico/betha/v1/cancelamento_nfs.rb +52 -0
- data/lib/br_nfe/servico/betha/v1/consulta_lote_rps.rb +31 -0
- data/lib/br_nfe/servico/betha/v1/consulta_nfs_por_rps.rb +34 -0
- data/lib/br_nfe/servico/betha/v1/consulta_nfse.rb +50 -0
- data/lib/br_nfe/servico/betha/v1/consulta_situacao_lote_rps.rb +18 -0
- data/lib/br_nfe/servico/betha/v1/gateway.rb +115 -0
- data/lib/br_nfe/servico/betha/v1/recepcao_lote_rps.rb +89 -0
- data/lib/br_nfe/servico/betha/v2/cancelamento_nfs.rb +25 -0
- data/lib/br_nfe/servico/betha/v2/consulta_lote_rps.rb +27 -0
- data/lib/br_nfe/servico/betha/v2/consulta_nfse_por_rps.rb +27 -0
- data/lib/br_nfe/servico/betha/v2/envio_lote_rps_sincrono.rb +26 -0
- data/lib/br_nfe/servico/betha/v2/gateway.rb +198 -0
- data/lib/br_nfe/servico/betha/v2/gera_nfse.rb +25 -0
- data/lib/br_nfe/servico/betha/v2/recepcao_lote_rps.rb +47 -0
- data/lib/br_nfe/servico/betha/v2/response.rb +23 -0
- data/lib/br_nfe/servico/betha/v2/substituicao_nfse.rb +39 -0
- data/lib/br_nfe/servico/intermediario.rb +17 -0
- data/lib/br_nfe/servico/response/default.rb +34 -0
- data/lib/br_nfe/servico/response/nota_fiscal.rb +73 -0
- data/lib/br_nfe/servico/rps.rb +103 -0
- data/lib/br_nfe/version.rb +8 -0
- data/lib/br_nfe.rb +146 -0
- data/test/br_nfe/base_test.rb +274 -0
- data/test/br_nfe/condicao_pagamento_test.rb +23 -0
- data/test/br_nfe/destinatario_test.rb +26 -0
- data/test/br_nfe/emitente_test.rb +26 -0
- data/test/br_nfe/endereco_test.rb +50 -0
- data/test/br_nfe/helper/have_address_test.rb +62 -0
- data/test/br_nfe/helper/have_condicao_pagamento_test.rb +71 -0
- data/test/br_nfe/helper/have_destinatario_test.rb +64 -0
- data/test/br_nfe/helper/have_emitente_test.rb +63 -0
- data/test/br_nfe/helper/have_intermediario_test.rb +77 -0
- data/test/br_nfe/helper/have_rps_test.rb +59 -0
- data/test/br_nfe/servico/base_test.rb +23 -0
- data/test/br_nfe/servico/betha/base_test.rb +106 -0
- data/test/br_nfe/servico/betha/v1/build_response_test.rb +558 -0
- data/test/br_nfe/servico/betha/v1/cancelamento_nfs_test.rb +62 -0
- data/test/br_nfe/servico/betha/v1/consulta_lote_rps_test.rb +42 -0
- data/test/br_nfe/servico/betha/v1/consulta_nfs_por_rps_test.rb +68 -0
- data/test/br_nfe/servico/betha/v1/consulta_nfse_test.rb +57 -0
- data/test/br_nfe/servico/betha/v1/consulta_situacao_lote_rps_test.rb +27 -0
- data/test/br_nfe/servico/betha/v1/gateway_test.rb +174 -0
- data/test/br_nfe/servico/betha/v1/recepcao_lote_rps_test.rb +235 -0
- data/test/br_nfe/servico/response/default_test.rb +54 -0
- data/test/br_nfe/servico/response/nota_fiscal_test.rb +41 -0
- data/test/br_nfe/servico/rps_test.rb +214 -0
- data/test/certificado.rb +12 -0
- data/test/factories/base.rb +5 -0
- data/test/factories/condicao_pagamento.rb +10 -0
- data/test/factories/destinatario.rb +11 -0
- data/test/factories/emitente.rb +15 -0
- data/test/factories/endereco.rb +12 -0
- data/test/factories/servico/base.rb +5 -0
- data/test/factories/servico/betha/base.rb +5 -0
- data/test/factories/servico/betha/v1/build_response.rb +6 -0
- data/test/factories/servico/betha/v1/cancelamento_nfs.rb +7 -0
- data/test/factories/servico/betha/v1/consulta_lote_rps.rb +6 -0
- data/test/factories/servico/betha/v1/consulta_nfs_por_rps.rb +6 -0
- data/test/factories/servico/betha/v1/consulta_nfse.rb +8 -0
- data/test/factories/servico/betha/v1/consulta_situacao_lote_rps.rb +6 -0
- data/test/factories/servico/betha/v1/gateway.rb +5 -0
- data/test/factories/servico/betha/v1/recepcao_lote_rps.rb +6 -0
- data/test/factories/servico/intermediario.rb +7 -0
- data/test/factories/servico/response/default.rb +10 -0
- data/test/factories/servico/response/nota_fiscal.rb +47 -0
- data/test/factories/servico/rps.rb +44 -0
- data/test/test_helper.rb +39 -0
- metadata +263 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Betha
|
|
4
|
+
module V2
|
|
5
|
+
class Gateway < BrNfe::Servico::Betha::Base
|
|
6
|
+
|
|
7
|
+
attr_accessor :numero_nfse
|
|
8
|
+
attr_accessor :codigo_cancelamento
|
|
9
|
+
|
|
10
|
+
def namespaces
|
|
11
|
+
{"xmlns:e" => "http://www.betha.com.br/e-nota-contribuinte-ws"}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def namespace_identifier
|
|
15
|
+
:e
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def version
|
|
19
|
+
:v2
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def wsdl
|
|
23
|
+
"http://e-gov.betha.com.br/e-nota-contribuinte-#{'test-' if env == :test}ws/nfseWS?wsdl"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def request
|
|
27
|
+
set_response( client_wsdl.call(method_wsdl, message: "#{cabecalho}#{content_xml}") )
|
|
28
|
+
rescue Savon::SOAPFault => error
|
|
29
|
+
return @response = BrNfe::Servico::Response::Default.new(success: false, error_messages: [error.message])
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def set_response(resp)
|
|
33
|
+
method_response = (method_wsdl.to_s + "_response").to_sym
|
|
34
|
+
@response = BrNfe::Servico::Betha::V2::Response.new(xml: resp.hash[:envelope][:body][method_response][:return], nfe_method: method_wsdl)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cabecalho
|
|
38
|
+
Nokogiri::XML::Builder.new do
|
|
39
|
+
nfseCabecMsg do
|
|
40
|
+
cdata(Nokogiri::XML::Builder.new do |xml|
|
|
41
|
+
xml.cabecalho(xmlns: "http://www.betha.com.br/e-nota-contribuinte-ws", versao: "2.02"){
|
|
42
|
+
xml.versaoDados 2.02
|
|
43
|
+
}
|
|
44
|
+
end.doc.root)
|
|
45
|
+
end
|
|
46
|
+
end.doc.root.to_s.gsub(/\n/,'').gsub(/\t/,'')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def content_xml
|
|
50
|
+
Nokogiri::XML::Builder.new do
|
|
51
|
+
nfseDadosMsg do
|
|
52
|
+
cdata(xml_builder)
|
|
53
|
+
end
|
|
54
|
+
end.doc.root.to_s
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def format_data_xml_for_signature(data_xml)
|
|
60
|
+
xml = Nokogiri::XML(data_xml.to_s, &:noblanks)
|
|
61
|
+
node_name = xml.root.node_name
|
|
62
|
+
xml = xml.root.xpath("//#{node_name}")
|
|
63
|
+
xml.attr("xmlns", "http://www.betha.com.br/e-nota-contribuinte-ws")
|
|
64
|
+
canonicalize xml.to_s
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def tag_intermediario_servico(xml, intermediario)
|
|
68
|
+
return unless intermediario
|
|
69
|
+
xml.Intermediario{
|
|
70
|
+
xml.IdentificacaoIntermediario{
|
|
71
|
+
xml.CpfCnpj{
|
|
72
|
+
tag_cpf_cnpj(xml, intermediario.cpf_cnpj)
|
|
73
|
+
}
|
|
74
|
+
xml.InscricaoMunicipal "#{intermediario.inscricao_municipal}".max_size(15) unless intermediario.inscricao_municipal.blank?
|
|
75
|
+
}
|
|
76
|
+
xml.RazaoSocial "#{intermediario.razao_social}".max_size(150)
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def tag_prestador(xml)
|
|
81
|
+
xml.Prestador{
|
|
82
|
+
xml.CpfCnpj{
|
|
83
|
+
tag_cpf_cnpj(xml, emitente.cnpj)
|
|
84
|
+
}
|
|
85
|
+
xml.InscricaoMunicipal "#{emitente.inscricao_municipal}".max_size(15) if !emitente.inscricao_municipal.blank? && env == :production
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def tag_dados_servico(xml, rps)
|
|
90
|
+
xml.Servico {
|
|
91
|
+
xml.Valores {
|
|
92
|
+
xml.ValorServicos value_monetary(rps.valor_servicos, 2)
|
|
93
|
+
xml.ValorDeducoes value_monetary(rps.valor_deducoes, 2) unless rps.valor_deducoes.blank?
|
|
94
|
+
xml.ValorPis value_monetary(rps.valor_pis, 2) unless rps.valor_pis.blank?
|
|
95
|
+
xml.ValorCofins value_monetary(rps.valor_cofins, 2) unless rps.valor_cofins.blank?
|
|
96
|
+
xml.ValorInss value_monetary(rps.valor_inss, 2) unless rps.valor_inss.blank?
|
|
97
|
+
xml.ValorIr value_monetary(rps.valor_ir, 2) unless rps.valor_ir.blank?
|
|
98
|
+
xml.ValorCsll value_monetary(rps.valor_csll, 2) unless rps.valor_csll.blank?
|
|
99
|
+
xml.OutrasRetencoes value_monetary(rps.outras_retencoes, 2) unless rps.outras_retencoes.blank?
|
|
100
|
+
xml.ValorIss value_monetary(rps.valor_iss, 2) unless rps.valor_iss.blank?
|
|
101
|
+
xml.Aliquota value_monetary(rps.aliquota, 2) unless rps.aliquota.blank?
|
|
102
|
+
xml.DescontoIncondicionado value_monetary(rps.desconto_incondicionado, 2) unless rps.desconto_incondicionado.blank?
|
|
103
|
+
xml.DescontoCondicionado value_monetary(rps.desconto_condicionado, 2) unless rps.desconto_condicionado.blank?
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
xml.IssRetido value_true_false(rps.iss_retido?)
|
|
107
|
+
xml.ResponsavelRetencao "#{rps.responsavel_retencao}".max_size(1) unless rps.responsavel_retencao.blank?
|
|
108
|
+
xml.ItemListaServico BrNfe::Helper.only_number(rps.item_lista_servico).rjust(4,'0').max_size(5)
|
|
109
|
+
xml.CodigoCnae BrNfe::Helper.only_number(rps.codigo_cnae).max_size(7) unless rps.codigo_cnae.blank?
|
|
110
|
+
xml.CodigoTributacaoMunicipio "#{rps.codigo_tributacao_municipio}".max_size(20) unless rps.codigo_tributacao_municipio.blank?
|
|
111
|
+
xml.Discriminacao "#{rps.discriminacao}".max_size(2_000).remove_accents
|
|
112
|
+
xml.CodigoMunicipio "#{rps.codigo_municipio}".max_size(7)
|
|
113
|
+
# Não posso enviar o CodigoPais se a exigibilidade_iss não for 4 (exportação) - by bethagambis.com
|
|
114
|
+
xml.CodigoPais rps.codigo_pais.max_size(4) if !rps.codigo_pais.blank? && rps.exigibilidade_iss == '4'
|
|
115
|
+
xml.ExigibilidadeISS "#{rps.exigibilidade_iss}".max_size(2)
|
|
116
|
+
xml.MunicipioIncidencia rps.municipio_incidencia.max_size(4) unless rps.municipio_incidencia.blank?
|
|
117
|
+
xml.NumeroProcesso rps.numero_processo.max_size(30) unless rps.numero_processo.blank?
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def xml_inf_declaracao_prestacao_servico(rps)
|
|
122
|
+
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
123
|
+
xml.InfDeclaracaoPrestacaoServico('Id' => "rps#{rps.numero}") {
|
|
124
|
+
xml.Rps {
|
|
125
|
+
tag_identificacao_rps(xml, rps)
|
|
126
|
+
|
|
127
|
+
xml.DataEmissao value_date(rps.data_emissao)
|
|
128
|
+
xml.Status "#{rps.status}".max_size(1)
|
|
129
|
+
|
|
130
|
+
tag_rps_substituido(xml, rps)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# Dia, mês e ano da prestação do serviço
|
|
134
|
+
# Quando houver RPS, a nota será gerada com base na <DataEmissao> do RPS, caso contrário utilizará a <Competencia>
|
|
135
|
+
xml.Competencia value_date(rps.competencia)
|
|
136
|
+
|
|
137
|
+
tag_dados_servico(xml, rps)
|
|
138
|
+
|
|
139
|
+
tag_prestador(xml)
|
|
140
|
+
|
|
141
|
+
tag_dados_tomador(xml, rps.destinatario)
|
|
142
|
+
|
|
143
|
+
tag_intermediario_servico(xml, rps.intermediario)
|
|
144
|
+
|
|
145
|
+
tag_dados_construcao_civil(xml, rps)
|
|
146
|
+
|
|
147
|
+
# Código de identificação do regime especial de tributação: (1)Microempresa municipal, (2)Estimativa, (3)Sociedade de profissionais, (4)Cooperativa, (5)Microempresário Individual (MEI), (6)Microempresário e Empresa de Pequeno Porte (ME EPP) ,
|
|
148
|
+
xml.RegimeEspecialTributacao emitente.regime_especial_tributacao.max_size(2) unless emitente.regime_especial_tributacao.blank?
|
|
149
|
+
|
|
150
|
+
xml.OptanteSimplesNacional value_true_false(emitente.optante_simples_nacional?) # (1)sim ----- (2)não
|
|
151
|
+
xml.IncentivoFiscal value_true_false(emitente.incentivo_fiscal?) # (1)sim ----- (2)não
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def xml_rps_assinado(rps)
|
|
158
|
+
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
159
|
+
xml.Rps{
|
|
160
|
+
arps = xml_inf_declaracao_prestacao_servico(rps).doc.root
|
|
161
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( arps.to_s )
|
|
162
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( assinatura_xml( arps.to_s, "#rps#{rps.numero}" ) )
|
|
163
|
+
}
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def xml_pedido_cancelamento_assinado
|
|
168
|
+
xml = Nokogiri::XML::Builder.new do |xml|
|
|
169
|
+
xml.Pedido {
|
|
170
|
+
inf_pedido_cancelamento = xml_inf_pedido_cancelamento.doc.root
|
|
171
|
+
|
|
172
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( inf_pedido_cancelamento.to_s )
|
|
173
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( assinatura_xml(inf_pedido_cancelamento.to_s, "#nf#{numero_nfse}") )
|
|
174
|
+
}
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def xml_inf_pedido_cancelamento
|
|
179
|
+
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
180
|
+
xml.InfPedidoCancelamento(Id: "nf#{numero_nfse}"){
|
|
181
|
+
xml.IdentificacaoNfse{
|
|
182
|
+
xml.Numero BrNfe::Helper.only_number(numero_nfse).max_size(15)
|
|
183
|
+
xml.CpfCnpj{
|
|
184
|
+
tag_cpf_cnpj(xml, emitente.cnpj)
|
|
185
|
+
}
|
|
186
|
+
xml.InscricaoMunicipal emitente.inscricao_municipal.max_size(15) if !emitente.inscricao_municipal.blank? && env == :production
|
|
187
|
+
xml.CodigoMunicipio "#{emitente.endereco.codigo_municipio}".max_size(7)
|
|
188
|
+
}
|
|
189
|
+
xml.CodigoCancelamento "#{codigo_cancelamento}".max_size(4)
|
|
190
|
+
}
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Betha
|
|
4
|
+
module V2
|
|
5
|
+
class GeraNfse < BrNfe::Servico::Betha::V2::Gateway
|
|
6
|
+
include BrNfe::Helper::HaveRps
|
|
7
|
+
|
|
8
|
+
def method_wsdl
|
|
9
|
+
:gerar_nfse
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def xml_builder
|
|
13
|
+
xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
14
|
+
xml.GerarNfseEnvio(xmlns: "http://www.betha.com.br/e-nota-contribuinte-ws") {
|
|
15
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_rps_assinado(rps).doc.root.to_s)
|
|
16
|
+
}
|
|
17
|
+
end.doc.root
|
|
18
|
+
|
|
19
|
+
canonicalize xml
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Betha
|
|
4
|
+
module V2
|
|
5
|
+
class RecepcaoLoteRps < BrNfe::Servico::Betha::V2::Gateway
|
|
6
|
+
def method_wsdl
|
|
7
|
+
:recepcionar_lote_rps
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def xml_builder
|
|
11
|
+
xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
12
|
+
xml.EnviarLoteRpsEnvio(xmlns: "http://www.betha.com.br/e-nota-contribuinte-ws") {
|
|
13
|
+
xml_lote_rps = lote_rps_xml.doc.root
|
|
14
|
+
|
|
15
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_lote_rps.to_s )
|
|
16
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( assinatura_xml(xml_lote_rps.to_s, "#lote#{numero_lote_rps}") )
|
|
17
|
+
}
|
|
18
|
+
end.doc.root
|
|
19
|
+
|
|
20
|
+
canonicalize xml
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def lote_rps_xml
|
|
25
|
+
xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
26
|
+
xml.LoteRps("Id" => "lote#{numero_lote_rps}", versao: "2.02"){
|
|
27
|
+
xml.NumeroLote BrNfe::Helper.only_number(numero_lote_rps).max_size(15)
|
|
28
|
+
xml.CpfCnpj {
|
|
29
|
+
tag_cpf_cnpj(xml, emitente.cnpj)
|
|
30
|
+
}
|
|
31
|
+
# O Ambiente de homologação da Betha não aceita Inscrição Municipal (baita ambiente de homologação)
|
|
32
|
+
xml.InscricaoMunicipal emitente.inscricao_municipal.max_size(15) if !emitente.inscricao_municipal.blank? && env == :production
|
|
33
|
+
|
|
34
|
+
xml.QuantidadeRps lote_rps.size
|
|
35
|
+
xml.ListaRps {
|
|
36
|
+
lote_rps.each do |obj_rps|
|
|
37
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_rps_assinado(obj_rps).doc.root.to_s)
|
|
38
|
+
end
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Betha
|
|
4
|
+
module V2
|
|
5
|
+
class Response < BrNfe::ActiveModelBase
|
|
6
|
+
attr_accessor :xml, :nfe_method
|
|
7
|
+
|
|
8
|
+
def messages
|
|
9
|
+
Nori.new(:convert_tags_to => lambda { |tag| tag.snakecase.to_sym }).parse(xml.to_s)["#{nfe_method.to_s}_resposta".to_sym]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def success?
|
|
13
|
+
raise "Não implementado"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def errors
|
|
17
|
+
raise "Não implementado"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Betha
|
|
4
|
+
module V2
|
|
5
|
+
class SubstituicaoNfse < BrNfe::Servico::Betha::V2::Gateway
|
|
6
|
+
include BrNfe::Helper::HaveRps
|
|
7
|
+
|
|
8
|
+
def method_wsdl
|
|
9
|
+
:substituir_nfse
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def xml_builder
|
|
13
|
+
xml = Nokogiri::XML::Builder.new do |xml|
|
|
14
|
+
xml.SubstituirNfseEnvio(xmlns: "http://www.betha.com.br/e-nota-contribuinte-ws") {
|
|
15
|
+
xml_substituicao = xml_substituicao_nfse.doc.root
|
|
16
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_substituicao.to_s )
|
|
17
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( assinatura_xml(xml_substituicao.to_s, "#substituicao") )
|
|
18
|
+
}
|
|
19
|
+
end.doc.root
|
|
20
|
+
|
|
21
|
+
canonicalize xml
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def xml_substituicao_nfse
|
|
26
|
+
Nokogiri::XML::Builder.new do |xml|
|
|
27
|
+
xml.SubstituicaoNfse(Id: "substituicao") {
|
|
28
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_pedido_cancelamento_assinado.doc.root.to_s )
|
|
29
|
+
xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_rps_assinado(rps).doc.root.to_s )
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
class Intermediario < BrNfe::ActiveModelBase
|
|
4
|
+
|
|
5
|
+
attr_accessor :cpf_cnpj
|
|
6
|
+
attr_accessor :inscricao_municipal
|
|
7
|
+
attr_accessor :razao_social
|
|
8
|
+
|
|
9
|
+
validates :cpf_cnpj, :razao_social, presence: true
|
|
10
|
+
|
|
11
|
+
def razao_social
|
|
12
|
+
"#{@razao_social}".to_valid_format_nf
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Response
|
|
4
|
+
class Default < BrNfe::ActiveModelBase
|
|
5
|
+
attr_accessor :success
|
|
6
|
+
attr_accessor :error_messages
|
|
7
|
+
attr_accessor :notas_fiscais
|
|
8
|
+
|
|
9
|
+
attr_accessor :protocolo
|
|
10
|
+
attr_accessor :data_recebimento
|
|
11
|
+
attr_accessor :numero_lote
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def initialize(attributes = {})
|
|
15
|
+
self.notas_fiscais = [] # Para poder utilizar o <<
|
|
16
|
+
self.error_messages = [] # Para poder utilizar o <<
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def notas_fiscais
|
|
21
|
+
@notas_fiscais = [@notas_fiscais].flatten # Para retornar sempre um vetor
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def error_messages
|
|
25
|
+
@error_messages = [@error_messages].flatten
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def success?
|
|
29
|
+
success
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
module Response
|
|
4
|
+
class NotaFiscal < BrNfe::ActiveModelBase
|
|
5
|
+
include BrNfe::Helper::HaveIntermediario
|
|
6
|
+
include BrNfe::Helper::HaveDestinatario
|
|
7
|
+
include BrNfe::Helper::HaveEmitente
|
|
8
|
+
include BrNfe::Helper::HaveCondicaoPagamento
|
|
9
|
+
|
|
10
|
+
attr_accessor :numero_nf
|
|
11
|
+
attr_accessor :codigo_verificacao
|
|
12
|
+
attr_accessor :data_emissao
|
|
13
|
+
attr_accessor :url_nf
|
|
14
|
+
|
|
15
|
+
#identificacao do rps
|
|
16
|
+
attr_accessor :rps_numero
|
|
17
|
+
attr_accessor :rps_serie
|
|
18
|
+
attr_accessor :rps_tipo
|
|
19
|
+
attr_accessor :rps_situacao
|
|
20
|
+
|
|
21
|
+
attr_accessor :data_emissao_rps # Datetime
|
|
22
|
+
attr_accessor :competencia #DateTime
|
|
23
|
+
attr_accessor :outras_informacoes
|
|
24
|
+
|
|
25
|
+
# dados dos serviços
|
|
26
|
+
attr_accessor :item_lista_servico
|
|
27
|
+
attr_accessor :codigo_cnae
|
|
28
|
+
attr_accessor :discriminacao
|
|
29
|
+
attr_accessor :codigo_municipio
|
|
30
|
+
|
|
31
|
+
#Valores dos serviços
|
|
32
|
+
attr_accessor :valor_servicos
|
|
33
|
+
attr_accessor :valor_deducoes
|
|
34
|
+
attr_accessor :valor_pis
|
|
35
|
+
attr_accessor :valor_cofins
|
|
36
|
+
attr_accessor :valor_inss
|
|
37
|
+
attr_accessor :valor_ir
|
|
38
|
+
attr_accessor :valor_csll
|
|
39
|
+
attr_accessor :iss_retido
|
|
40
|
+
attr_accessor :valor_iss
|
|
41
|
+
attr_accessor :base_calculo
|
|
42
|
+
attr_accessor :aliquota
|
|
43
|
+
attr_accessor :desconto_condicionado
|
|
44
|
+
attr_accessor :desconto_incondicionado
|
|
45
|
+
|
|
46
|
+
# Orgão gerador
|
|
47
|
+
attr_accessor :orgao_gerador_municipio
|
|
48
|
+
attr_accessor :orgao_gerador_uf
|
|
49
|
+
|
|
50
|
+
# Dados de cancelamento da NF
|
|
51
|
+
attr_accessor :cancelamento_codigo
|
|
52
|
+
attr_accessor :cancelamento_numero_nf
|
|
53
|
+
attr_accessor :cancelamento_cnpj
|
|
54
|
+
attr_accessor :cancelamento_inscricao_municipal
|
|
55
|
+
attr_accessor :cancelamento_municipio
|
|
56
|
+
attr_accessor :cancelamento_sucesso
|
|
57
|
+
attr_accessor :cancelamento_data_hora
|
|
58
|
+
|
|
59
|
+
# Se a NF foi substituida
|
|
60
|
+
attr_accessor :nfe_substituidora
|
|
61
|
+
def substituida?
|
|
62
|
+
!nfe_substituidora.blank?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# dados de construcao civil
|
|
66
|
+
attr_accessor :codigo_obra
|
|
67
|
+
attr_accessor :codigo_art
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Servico
|
|
3
|
+
class Rps < BrNfe::ActiveModelBase
|
|
4
|
+
include BrNfe::Helper::HaveDestinatario
|
|
5
|
+
include BrNfe::Helper::HaveIntermediario
|
|
6
|
+
include BrNfe::Helper::HaveCondicaoPagamento
|
|
7
|
+
|
|
8
|
+
attr_accessor :validar_recepcao_rps
|
|
9
|
+
|
|
10
|
+
# Sempre que houver RPS, essas informações são obrigatórias
|
|
11
|
+
validates :numero, :serie, :tipo, presence: true
|
|
12
|
+
|
|
13
|
+
with_options if: :validar_recepcao_rps do |record|
|
|
14
|
+
record.validates :data_emissao, :item_lista_servico, :discriminacao, :codigo_municipio,
|
|
15
|
+
:valor_servicos, :base_calculo, presence: true
|
|
16
|
+
record.validates :valor_iss, :aliquota, presence: true, unless: :iss_retido?
|
|
17
|
+
|
|
18
|
+
record.validates :valor_servicos, :valor_deducoes, :valor_pis, :valor_cofins, :valor_inss, :valor_ir,
|
|
19
|
+
:valor_csll, :outras_retencoes, :valor_iss, :aliquota, :base_calculo,
|
|
20
|
+
:desconto_incondicionado, :desconto_condicionado, numericality: true, allow_blank: true
|
|
21
|
+
|
|
22
|
+
record.validate :validar_intermediario
|
|
23
|
+
record.validate :validar_destinatario
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_accessor :numero
|
|
27
|
+
attr_accessor :serie
|
|
28
|
+
attr_accessor :tipo
|
|
29
|
+
|
|
30
|
+
attr_accessor :data_emissao
|
|
31
|
+
attr_accessor :status
|
|
32
|
+
attr_accessor :competencia
|
|
33
|
+
|
|
34
|
+
attr_accessor :numero_substituicao
|
|
35
|
+
attr_accessor :serie_substituicao
|
|
36
|
+
attr_accessor :tipo_substituicao
|
|
37
|
+
|
|
38
|
+
#Para construção civil
|
|
39
|
+
attr_accessor :codigo_obra
|
|
40
|
+
attr_accessor :codigo_art
|
|
41
|
+
|
|
42
|
+
attr_accessor :valor_servicos
|
|
43
|
+
attr_accessor :valor_deducoes
|
|
44
|
+
attr_accessor :valor_pis
|
|
45
|
+
attr_accessor :valor_cofins
|
|
46
|
+
attr_accessor :valor_inss
|
|
47
|
+
attr_accessor :valor_ir
|
|
48
|
+
attr_accessor :valor_csll
|
|
49
|
+
attr_accessor :outras_retencoes
|
|
50
|
+
attr_accessor :iss_retido
|
|
51
|
+
attr_accessor :valor_iss
|
|
52
|
+
attr_accessor :aliquota
|
|
53
|
+
attr_accessor :base_calculo
|
|
54
|
+
attr_accessor :desconto_incondicionado
|
|
55
|
+
attr_accessor :desconto_condicionado
|
|
56
|
+
|
|
57
|
+
attr_accessor :responsavel_retencao
|
|
58
|
+
attr_accessor :item_lista_servico
|
|
59
|
+
attr_accessor :codigo_tributacao_municipio
|
|
60
|
+
attr_accessor :discriminacao
|
|
61
|
+
attr_accessor :exigibilidade_iss
|
|
62
|
+
attr_accessor :codigo_municipio
|
|
63
|
+
attr_accessor :municipio_incidencia
|
|
64
|
+
attr_accessor :codigo_pais
|
|
65
|
+
attr_accessor :numero_processo
|
|
66
|
+
attr_accessor :codigo_cnae
|
|
67
|
+
attr_accessor :outras_informacoes
|
|
68
|
+
|
|
69
|
+
def contem_substituicao?
|
|
70
|
+
numero_substituicao.present? && serie_substituicao.present? && tipo_substituicao.present?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def iss_retido?
|
|
74
|
+
BrNfe.true_values.include?(iss_retido)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def competencia
|
|
78
|
+
@competencia || data_emissao
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def default_values
|
|
82
|
+
{
|
|
83
|
+
codigo_pais: '1058',
|
|
84
|
+
validar_recepcao_rps: false
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def validar_intermediario
|
|
90
|
+
return true unless intermediario
|
|
91
|
+
if intermediario.invalid?
|
|
92
|
+
intermediario.errors.full_messages.map{|msg| errors.add(:intermediario, msg) }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def validar_destinatario
|
|
97
|
+
if destinatario.invalid?
|
|
98
|
+
destinatario.errors.full_messages.map{|msg| errors.add(:destinatario, msg) }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module BrNfe
|
|
2
|
+
module Version
|
|
3
|
+
MAJOR = 1 #inclui alterações de API e pode quebrar compatibilidade com versões anteriores
|
|
4
|
+
MINOR = 0 #inclui novas funcionalidades, sem quebrar APIs existentes
|
|
5
|
+
PATCH = 0 #corrige bugs ou traz melhorias em implementações já existentes
|
|
6
|
+
CURRENT = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
|
7
|
+
end
|
|
8
|
+
end
|