afipws 0.0.1 → 0.1.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.
- data/.autotest +2 -0
- data/Gemfile.lock +9 -9
- data/README.rdoc +7 -4
- data/afipws.gemspec +2 -0
- data/lib/afipws/type_conversions.rb +5 -4
- data/lib/afipws/version.rb +1 -1
- data/lib/afipws/wsaa.rb +4 -3
- data/lib/afipws/wsfe.rb +56 -4
- data/lib/afipws.rb +1 -3
- data/spec/afipws/wsfe_spec.rb +84 -7
- data/spec/fixtures/fe_param_get_ptos_venta/success.xml +22 -0
- data/spec/fixtures/fecae_solicitar/{observaciones.xml → dos_observaciones.xml} +0 -0
- data/spec/fixtures/fecae_solicitar/una_observacion.xml +36 -0
- data/spec/fixtures/fecaea_consultar/success.xml +17 -0
- data/spec/fixtures/fecaea_reg_informativo/informe_rtdo_parcial.xml +45 -0
- data/spec/fixtures/fecaea_solicitar/caea_ya_otorgado.xml +18 -0
- data/spec/fixtures/fecaea_solicitar/success.xml +17 -0
- data/spec/manual/test.rb +44 -0
- metadata +48 -12
- data/lib/core_ext/string.rb +0 -9
- data/spec/manual/autorizar_comprobante.rb +0 -22
- data/spec/manual/obtener_ta.rb +0 -18
data/.autotest
ADDED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
afipws (0.0
|
4
|
+
afipws (0.1.0)
|
5
5
|
activesupport
|
6
6
|
builder
|
7
|
+
httpclient
|
8
|
+
i18n
|
7
9
|
nokogiri
|
8
10
|
savon
|
9
11
|
|
@@ -12,14 +14,16 @@ GEM
|
|
12
14
|
specs:
|
13
15
|
activesupport (3.0.3)
|
14
16
|
archive-tar-minitar (0.5.2)
|
15
|
-
builder (
|
17
|
+
builder (3.0.0)
|
16
18
|
columnize (0.3.2)
|
17
19
|
crack (0.1.8)
|
18
20
|
diff-lcs (1.1.2)
|
19
21
|
gyoku (0.2.0)
|
20
22
|
builder (>= 2.1.2)
|
23
|
+
httpclient (2.1.6.1)
|
21
24
|
httpi (0.7.8)
|
22
25
|
rack
|
26
|
+
i18n (0.5.0)
|
23
27
|
linecache19 (0.5.11)
|
24
28
|
ruby_core_source (>= 0.1.4)
|
25
29
|
mocha (0.9.10)
|
@@ -45,11 +49,11 @@ GEM
|
|
45
49
|
ruby-debug-base19 (>= 0.11.19)
|
46
50
|
ruby_core_source (0.1.4)
|
47
51
|
archive-tar-minitar (>= 0.5.2)
|
48
|
-
savon (0.8.
|
52
|
+
savon (0.8.3)
|
49
53
|
builder (>= 2.1.2)
|
50
54
|
crack (~> 0.1.8)
|
51
|
-
gyoku (>= 0.
|
52
|
-
httpi (>= 0.7.
|
55
|
+
gyoku (>= 0.2.0)
|
56
|
+
httpi (>= 0.7.8)
|
53
57
|
savon_spec (0.1.2)
|
54
58
|
mocha (>= 0.9.8)
|
55
59
|
rspec (>= 2.0.0)
|
@@ -59,11 +63,7 @@ PLATFORMS
|
|
59
63
|
ruby
|
60
64
|
|
61
65
|
DEPENDENCIES
|
62
|
-
activesupport
|
63
66
|
afipws!
|
64
|
-
builder
|
65
|
-
nokogiri
|
66
67
|
rspec
|
67
68
|
ruby-debug19
|
68
|
-
savon
|
69
69
|
savon_spec
|
data/README.rdoc
CHANGED
@@ -2,13 +2,16 @@
|
|
2
2
|
|
3
3
|
== Uso
|
4
4
|
|
5
|
-
Primero hay que crear la clave privada y obtener el certificado correspondiente según los pasos indicados {aquí}[http://www.
|
6
|
-
Luego usamos el Web Service de la siguiente forma:
|
5
|
+
Primero hay que crear la clave privada y obtener el certificado correspondiente según los pasos indicados {aquí}[http://www.afip.gov.ar/ws/WSAA/cert-req-howto.txt].
|
7
6
|
|
8
|
-
|
7
|
+
Luego hay que instalar la librería:
|
8
|
+
|
9
|
+
gem install afipws
|
10
|
+
|
11
|
+
Y por último usamos el web service de esta forma:
|
9
12
|
|
10
13
|
require 'afipws'
|
11
|
-
ws = Afipws::WSFE.new :env => :
|
14
|
+
ws = Afipws::WSFE.new :env => :development, :cuit => '...', :key => File.read('test.key') , :cert => File.read('test.crt')
|
12
15
|
puts ws.cotizacion 'DOL'
|
13
16
|
|
14
17
|
De momento sólo están soportados los servicios WSAA y WSFEv1.
|
data/afipws.gemspec
CHANGED
@@ -22,10 +22,11 @@ module Afipws
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def parsing_fn
|
25
|
-
@parsing ||= Hash.new(Proc.new { |
|
26
|
-
p[:date] = Proc.new { |
|
27
|
-
p[:integer] = Proc.new { |
|
28
|
-
p[:float] = Proc.new { |
|
25
|
+
@parsing ||= Hash.new(Proc.new { |v| v }).tap { |p|
|
26
|
+
p[:date] = Proc.new { |v| ::Date.parse(v) rescue nil }
|
27
|
+
p[:integer] = Proc.new { |v| v.to_i }
|
28
|
+
p[:float] = Proc.new { |v| v.to_f }
|
29
|
+
p[:boolean] = Proc.new { |v| v == "S" }
|
29
30
|
}
|
30
31
|
end
|
31
32
|
|
data/lib/afipws/version.rb
CHANGED
data/lib/afipws/wsaa.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Afipws
|
2
2
|
class WSAA
|
3
|
-
attr_reader :key, :cert, :service, :ta, :cuit
|
3
|
+
attr_reader :key, :cert, :service, :ta, :cuit, :client
|
4
4
|
|
5
5
|
WSDL = {
|
6
|
-
:
|
6
|
+
:development => "https://wsaahomo.afip.gov.ar/ws/services/LoginCms?wsdl",
|
7
|
+
:production => 'https://wsaa.afip.gov.ar/ws/services/LoginCms?wsdl',
|
7
8
|
:test => Root + '/spec/fixtures/wsaa.wsdl'
|
8
9
|
}
|
9
10
|
|
@@ -58,7 +59,7 @@ module Afipws
|
|
58
59
|
# en los otros WS.
|
59
60
|
def auth
|
60
61
|
@ta = login if ta_expirado?
|
61
|
-
{ :auth => { :token => @ta[:token], :sign => ta[:sign], :cuit => @cuit } }
|
62
|
+
{ :auth => { :token => @ta[:token], :sign => @ta[:sign], :cuit => @cuit } }
|
62
63
|
end
|
63
64
|
|
64
65
|
private
|
data/lib/afipws/wsfe.rb
CHANGED
@@ -6,7 +6,8 @@ module Afipws
|
|
6
6
|
def_delegators :wsaa, :ta, :auth, :cuit
|
7
7
|
|
8
8
|
WSDL = {
|
9
|
-
:
|
9
|
+
:development => "https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL",
|
10
|
+
:production => "https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL",
|
10
11
|
:test => Root + '/spec/fixtures/wsfe.wsdl'
|
11
12
|
}
|
12
13
|
|
@@ -44,6 +45,12 @@ module Afipws
|
|
44
45
|
x2r get_array(r, :tributo_tipo), :id => :integer, :fch_desde => :date, :fch_hasta => :date
|
45
46
|
end
|
46
47
|
|
48
|
+
# TODO probar una vez q habiliten algunos ptos de venta
|
49
|
+
def puntos_venta
|
50
|
+
r = @client.fe_param_get_ptos_venta auth
|
51
|
+
x2r get_array(r, :pto_venta), :nro => :integer, :fch_baja => :date, :bloqueado => :boolean
|
52
|
+
end
|
53
|
+
|
47
54
|
def cotizacion moneda_id
|
48
55
|
@client.fe_param_get_cotizacion(auth.merge(:mon_id => moneda_id))[:result_get][:mon_cotiz].to_f
|
49
56
|
end
|
@@ -62,12 +69,40 @@ module Afipws
|
|
62
69
|
}}}
|
63
70
|
r = @client.fecae_solicitar auth.merge r2x(request, :cbte_fch => :date)
|
64
71
|
r = Array.wrap(r[:fe_det_resp][:fecae_det_response]).map do |h|
|
65
|
-
obs = h[:observaciones] ? h[:observaciones][:obs] : nil
|
66
|
-
h.select_keys(:cae, :cae_fch_vto).merge(:cbte_nro => h[:cbte_desde]
|
72
|
+
obs = Array.wrap(h[:observaciones] ? h[:observaciones][:obs] : nil)
|
73
|
+
h.select_keys(:cae, :cae_fch_vto, :resultado).merge(:cbte_nro => h[:cbte_desde], :observaciones => obs)
|
67
74
|
end
|
68
75
|
x2r r, :cae_fch_vto => :date, :cbte_nro => :integer, :code => :integer
|
69
76
|
end
|
70
77
|
|
78
|
+
def solicitar_caea
|
79
|
+
convertir_rta_caea @client.fecaea_solicitar auth.merge(periodo_para_solicitud_caea)
|
80
|
+
end
|
81
|
+
|
82
|
+
def consultar_caea fecha
|
83
|
+
convertir_rta_caea @client.fecaea_consultar auth.merge(periodo_para_consulta_caea(fecha))
|
84
|
+
end
|
85
|
+
|
86
|
+
def informar_comprobantes_caea opciones
|
87
|
+
comprobantes = opciones[:comprobantes]
|
88
|
+
request = { 'FeCAEARegInfReq' => {
|
89
|
+
'FeCabReq' => opciones.select_keys(:cbte_tipo, :pto_vta).merge(:cant_reg => comprobantes.size),
|
90
|
+
'FeDetReq' => {
|
91
|
+
'FECAEADetRequest' => comprobantes.map do |comprobante|
|
92
|
+
comprobante.merge(:cbte_desde => comprobante[:cbte_nro], :cbte_hasta => comprobante[:cbte_nro]).
|
93
|
+
select_keys(:concepto, :doc_tipo, :doc_nro, :cbte_desde,
|
94
|
+
:cbte_hasta, :cbte_fch, :imp_total, :imp_tot_conc, :imp_neto, :imp_op_ex, :imp_trib,
|
95
|
+
:mon_id, :mon_cotiz, :iva).merge({ 'ImpIVA' => comprobante[:imp_iva], 'CAEA' => comprobante[:caea] })
|
96
|
+
end
|
97
|
+
}}}
|
98
|
+
r = @client.fecaea_reg_informativo auth.merge r2x(request, :cbte_fch => :date)
|
99
|
+
r = Array.wrap(r[:fe_det_resp][:fecaea_det_response]).map do |h|
|
100
|
+
obs = Array.wrap(h[:observaciones] ? h[:observaciones][:obs] : nil)
|
101
|
+
h.select_keys(:caea, :resultado).merge(:cbte_nro => h[:cbte_desde], :observaciones => obs)
|
102
|
+
end
|
103
|
+
x2r r, :cbte_nro => :integer, :code => :integer
|
104
|
+
end
|
105
|
+
|
71
106
|
def ultimo_comprobante_autorizado opciones
|
72
107
|
@client.fe_comp_ultimo_autorizado(auth.merge(opciones))[:cbte_nro].to_i
|
73
108
|
end
|
@@ -77,12 +112,29 @@ module Afipws
|
|
77
112
|
end
|
78
113
|
|
79
114
|
def cant_max_registros_x_request
|
80
|
-
@client.fe_comp_tot_x_request[:reg_x_req].to_i
|
115
|
+
@client.fe_comp_tot_x_request(auth)[:reg_x_req].to_i
|
116
|
+
end
|
117
|
+
|
118
|
+
def periodo_para_solicitud_caea
|
119
|
+
if Date.today.day <= 15
|
120
|
+
{ :orden => 2, :periodo => Date.today.strftime('%Y%m') }
|
121
|
+
else
|
122
|
+
{ :orden => 1, :periodo => Date.today.next_month.strftime('%Y%m') }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def periodo_para_consulta_caea fecha
|
127
|
+
orden = fecha.day <= 15 ? 1 : 2
|
128
|
+
{ :orden => orden, :periodo => fecha.strftime('%Y%m') }
|
81
129
|
end
|
82
130
|
|
83
131
|
private
|
84
132
|
def get_array response, array_element
|
85
133
|
Array.wrap response[:result_get][array_element]
|
86
134
|
end
|
135
|
+
|
136
|
+
def convertir_rta_caea r
|
137
|
+
x2r r[:result_get], :fch_tope_inf => :date, :fch_vig_desde => :date, :fch_vig_hasta => :date
|
138
|
+
end
|
87
139
|
end
|
88
140
|
end
|
data/lib/afipws.rb
CHANGED
@@ -7,9 +7,7 @@ require 'builder'
|
|
7
7
|
require 'base64'
|
8
8
|
require 'savon'
|
9
9
|
require 'nokogiri'
|
10
|
-
require 'active_support/core_ext
|
11
|
-
# TODO reemplazar wrap x un local
|
12
|
-
require 'core_ext/string'
|
10
|
+
require 'active_support/core_ext'
|
13
11
|
require 'core_ext/hash'
|
14
12
|
require 'afipws/excepciones'
|
15
13
|
require 'afipws/type_conversions'
|
data/spec/afipws/wsfe_spec.rb
CHANGED
@@ -43,6 +43,14 @@ describe Afipws::WSFE do
|
|
43
43
|
ws.tipos_tributos.should == [{ :id => 2, :desc => "Impuestos provinciales", :fch_desde => Date.new(2010,9,17), :fch_hasta => nil }]
|
44
44
|
end
|
45
45
|
|
46
|
+
it "puntos_venta" do
|
47
|
+
savon.expects('FEParamGetPtosVenta').returns(:success)
|
48
|
+
ws.puntos_venta.should == [
|
49
|
+
{ :nro => 1, :emision_tipo => "CAE", :bloqueado => false, :fch_baja => nil },
|
50
|
+
{ :nro => 2, :emision_tipo => "CAEA", :bloqueado => true, :fch_baja => Date.new(2011,1,31) }
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
46
54
|
context "cotizacion" do
|
47
55
|
it "cuando la moneda solicitada existe" do
|
48
56
|
savon.expects('FEParamGetCotizacion').with(has_path '/MonId' => 'DOL').returns(:dolar)
|
@@ -50,19 +58,20 @@ describe Afipws::WSFE do
|
|
50
58
|
end
|
51
59
|
|
52
60
|
it "cuando la moneda no existe" do
|
53
|
-
savon.expects('FEParamGetCotizacion').with(has_path '/MonId' => 'PES').returns(:inexistente)
|
61
|
+
savon.expects('FEParamGetCotizacion').with(has_path '/Auth/Token' => 't', '/MonId' => 'PES').returns(:inexistente)
|
54
62
|
expect { ws.cotizacion('PES') }.to raise_error Afipws::WSError, /602: Sin Resultados/
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
58
66
|
it "cant_max_registros_x_request" do
|
59
|
-
savon.expects('FECompTotXRequest').returns(:success)
|
67
|
+
savon.expects('FECompTotXRequest').with(has_path '/Auth/Token' => 't').returns(:success)
|
60
68
|
ws.cant_max_registros_x_request.should == 250
|
61
69
|
end
|
62
70
|
|
63
71
|
context "autorizar_comprobante" do
|
64
72
|
it "debería devolver un hash con el CAE y su fecha de vencimiento" do
|
65
|
-
savon.expects('FECAESolicitar').with(has_path '/
|
73
|
+
savon.expects('FECAESolicitar').with(has_path '/Auth/Token' => 't',
|
74
|
+
'/FeCAEReq/FeCabReq/CantReg' => 1,
|
66
75
|
'/FeCAEReq/FeCabReq/PtoVta' => 2,
|
67
76
|
'/FeCAEReq/FeCabReq/CbteTipo' => 1,
|
68
77
|
'/FeCAEReq/FeDetReq/FECAEDetRequest[0]/DocTipo' => 80,
|
@@ -78,7 +87,8 @@ describe Afipws::WSFE do
|
|
78
87
|
:imp_total => 1270.48, :imp_neto => 1049.98, :imp_iva => 220.50, :mon_id => 'PES', :mon_cotiz => 1,
|
79
88
|
:iva => { :alic_iva => [{ :id => 5, :base_imp => 1049.98, :importe => 220.50 }]}
|
80
89
|
}])
|
81
|
-
rta[0].should have_entries :cae => '61023008595705', :cae_fch_vto => Date.new(2011,01,23), :cbte_nro => 1
|
90
|
+
rta[0].should have_entries :cae => '61023008595705', :cae_fch_vto => Date.new(2011,01,23), :cbte_nro => 1,
|
91
|
+
:resultado => 'A', :observaciones => []
|
82
92
|
rta.should have(1).item
|
83
93
|
end
|
84
94
|
|
@@ -99,7 +109,9 @@ describe Afipws::WSFE do
|
|
99
109
|
savon.expects('FECAESolicitar').with(has_path({
|
100
110
|
'/FeCAEReq/FeCabReq/CantReg' => 2,
|
101
111
|
'/FeCAEReq/FeDetReq/FECAEDetRequest[0]/CbteDesde' => 5,
|
112
|
+
'/FeCAEReq/FeDetReq/FECAEDetRequest[0]/CbteHasta' => 5,
|
102
113
|
'/FeCAEReq/FeDetReq/FECAEDetRequest[1]/CbteDesde' => 6,
|
114
|
+
'/FeCAEReq/FeDetReq/FECAEDetRequest[1]/CbteHasta' => 6,
|
103
115
|
})).returns(:autorizacion_2_cbtes)
|
104
116
|
rta = ws.autorizar_comprobantes(:cbte_tipo => 1, :pto_vta => 2, :comprobantes => [
|
105
117
|
{ :cbte_nro => 5 }, { :cbte_nro => 6 }
|
@@ -108,12 +120,77 @@ describe Afipws::WSFE do
|
|
108
120
|
rta[1].should have_entries :cbte_nro => 6, :cae => '61033008894101'
|
109
121
|
end
|
110
122
|
|
111
|
-
it "con observaciones" do
|
112
|
-
savon.stubs('FECAESolicitar').returns(:
|
123
|
+
it "con 2 observaciones" do
|
124
|
+
savon.stubs('FECAESolicitar').returns(:dos_observaciones)
|
113
125
|
rta = ws.autorizar_comprobantes :comprobantes => []
|
114
|
-
rta[0].should have_entries :cbte_nro => 3, :cae => nil, :observaciones => [
|
126
|
+
rta[0].should have_entries :cbte_nro => 3, :cae => nil, :resultado => 'R', :observaciones => [
|
115
127
|
{:code => 10048, :msg => 'Msg 1'}, {:code => 10018, :msg => 'Msg 2'}]
|
116
128
|
end
|
129
|
+
|
130
|
+
it "con 1 observación" do
|
131
|
+
savon.stubs('FECAESolicitar').returns(:una_observacion)
|
132
|
+
rta = ws.autorizar_comprobantes :comprobantes => []
|
133
|
+
rta[0].should have_entries :observaciones => [{:code => 10048, :msg => 'Msg 1'}]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "solicitar_caea" do
|
138
|
+
it "debería mandar automáticamente el período y orden" do
|
139
|
+
Date.stubs :today => Date.new(2011,1,27)
|
140
|
+
savon.expects('FECAEASolicitar').with(has_path '/Periodo' => '201102', '/Orden' => 1).returns(:success)
|
141
|
+
ws.solicitar_caea.should have_entries :caea => '21043476341977', :fch_tope_inf => Date.new(2011,03,17),
|
142
|
+
:fch_vig_desde => Date.new(2011,02,01), :fch_vig_hasta => Date.new(2011,02,15)
|
143
|
+
end
|
144
|
+
|
145
|
+
context "periodo_para_solicitud_caea" do
|
146
|
+
it "cuando estoy en la primer quincena" do
|
147
|
+
Date.stubs :today => Date.new(2011,1,12)
|
148
|
+
ws.periodo_para_solicitud_caea.should == { :periodo => '201101', :orden => 2 }
|
149
|
+
Date.stubs :today => Date.new(2011,1,15)
|
150
|
+
ws.periodo_para_solicitud_caea.should == { :periodo => '201101', :orden => 2 }
|
151
|
+
end
|
152
|
+
|
153
|
+
it "cuando estoy en la segunda quincena" do
|
154
|
+
Date.stubs :today => Date.new(2011,1,16)
|
155
|
+
ws.periodo_para_solicitud_caea.should == { :periodo => '201102', :orden => 1 }
|
156
|
+
Date.stubs :today => Date.new(2011,1,31)
|
157
|
+
ws.periodo_para_solicitud_caea.should == { :periodo => '201102', :orden => 1 }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it "informar_comprobantes_caea" do
|
163
|
+
savon.expects('FECAEARegInformativo').with(has_path({ '/Auth/Token' => 't',
|
164
|
+
'/FeCAEARegInfReq/FeCabReq/CantReg' => 2,
|
165
|
+
'/FeCAEARegInfReq/FeCabReq/PtoVta' => 3,
|
166
|
+
'/FeCAEARegInfReq/FeCabReq/CbteTipo' => 1,
|
167
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[0]/CbteDesde' => 1,
|
168
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[0]/CbteHasta' => 1,
|
169
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[0]/CAEA' => '21043476341977',
|
170
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CbteDesde' => 2,
|
171
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CbteHasta' => 2,
|
172
|
+
'/FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CAEA' => '21043476341977',
|
173
|
+
})).returns(:informe_rtdo_parcial)
|
174
|
+
rta = ws.informar_comprobantes_caea(:cbte_tipo => 1, :pto_vta => 3, :comprobantes => [
|
175
|
+
{ :cbte_nro => 1, :caea => '21043476341977' }, { :cbte_nro => 2, :caea => '21043476341977' },
|
176
|
+
])
|
177
|
+
rta[0].should have_entries :cbte_nro => 1, :caea => '21043476341977', :resultado => 'A', :observaciones => []
|
178
|
+
rta[1].should have_entries :cbte_nro => 2, :caea => '21043476341977', :resultado => 'R', :observaciones => [{:code => 724, :msg => 'Msg'}]
|
179
|
+
end
|
180
|
+
|
181
|
+
context "consultar_caea" do
|
182
|
+
it "consultar_caea" do
|
183
|
+
savon.expects('FECAEAConsultar').with(has_path '/Periodo' => '201101', '/Orden' => 1).returns(:success)
|
184
|
+
ws.consultar_caea(Date.new(2011,1,1)).should have_entries :caea => '21043476341977', :fch_tope_inf => Date.new(2011,03,17)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "periodo_para_consulta_caea" do
|
188
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,1)).should == { :periodo => '201101', :orden => 1 }
|
189
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,15)).should == { :periodo => '201101', :orden => 1 }
|
190
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,16)).should == { :periodo => '201101', :orden => 2 }
|
191
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,31)).should == { :periodo => '201101', :orden => 2 }
|
192
|
+
ws.periodo_para_consulta_caea(Date.new(2011,2,2)).should == { :periodo => '201102', :orden => 1 }
|
193
|
+
end
|
117
194
|
end
|
118
195
|
|
119
196
|
it "ultimo_comprobante_autorizado" do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FEParamGetPtosVentaResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FEParamGetPtosVentaResult>
|
5
|
+
<ResultGet>
|
6
|
+
<PtoVenta>
|
7
|
+
<Nro>0001</Nro>
|
8
|
+
<EmisionTipo>CAE</EmisionTipo>
|
9
|
+
<Bloqueado>N</Bloqueado>
|
10
|
+
<FchBaja></FchBaja>
|
11
|
+
</PtoVenta>
|
12
|
+
<PtoVenta>
|
13
|
+
<Nro>0002</Nro>
|
14
|
+
<EmisionTipo>CAEA</EmisionTipo>
|
15
|
+
<Bloqueado>S</Bloqueado>
|
16
|
+
<FchBaja>20110131</FchBaja>
|
17
|
+
</PtoVenta>
|
18
|
+
</ResultGet>
|
19
|
+
</FEParamGetPtosVentaResult>
|
20
|
+
</FEParamGetPtosVentaResponse>
|
21
|
+
</soap:Body>
|
22
|
+
</soap:Envelope>
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FECAESolicitarResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FECAESolicitarResult>
|
5
|
+
<FeCabResp>
|
6
|
+
<Cuit>20300032673</Cuit>
|
7
|
+
<PtoVta>1</PtoVta>
|
8
|
+
<CbteTipo>1</CbteTipo>
|
9
|
+
<FchProceso>20110114</FchProceso>
|
10
|
+
<CantReg>1</CantReg>
|
11
|
+
<Resultado>R</Resultado>
|
12
|
+
<Reproceso>N</Reproceso>
|
13
|
+
</FeCabResp>
|
14
|
+
<FeDetResp>
|
15
|
+
<FECAEDetResponse>
|
16
|
+
<Concepto>1</Concepto>
|
17
|
+
<DocTipo>80</DocTipo>
|
18
|
+
<DocNro>30521189203</DocNro>
|
19
|
+
<CbteDesde>3</CbteDesde>
|
20
|
+
<CbteHasta>3</CbteHasta>
|
21
|
+
<CbteFch>20110113</CbteFch>
|
22
|
+
<Resultado>R</Resultado>
|
23
|
+
<Observaciones>
|
24
|
+
<Obs>
|
25
|
+
<Code>10048</Code>
|
26
|
+
<Msg>Msg 1</Msg>
|
27
|
+
</Obs>
|
28
|
+
</Observaciones>
|
29
|
+
<CAE/>
|
30
|
+
<CAEFchVto/>
|
31
|
+
</FECAEDetResponse>
|
32
|
+
</FeDetResp>
|
33
|
+
</FECAESolicitarResult>
|
34
|
+
</FECAESolicitarResponse>
|
35
|
+
</soap:Body>
|
36
|
+
</soap:Envelope>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FECAEAConsultarResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FECAEAConsultarResult>
|
5
|
+
<ResultGet>
|
6
|
+
<CAEA>21043476341977</CAEA>
|
7
|
+
<Periodo>201102</Periodo>
|
8
|
+
<Orden>1</Orden>
|
9
|
+
<FchVigDesde>20110201</FchVigDesde>
|
10
|
+
<FchVigHasta>20110215</FchVigHasta>
|
11
|
+
<FchTopeInf>20110317</FchTopeInf>
|
12
|
+
<FchProceso>20110127124928</FchProceso>
|
13
|
+
</ResultGet>
|
14
|
+
</FECAEAConsultarResult>
|
15
|
+
</FECAEAConsultarResponse>
|
16
|
+
</soap:Body>
|
17
|
+
</soap:Envelope>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FECAEARegInformativoResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FECAEARegInformativoResult>
|
5
|
+
<FeCabResp>
|
6
|
+
<Cuit>20300032673</Cuit>
|
7
|
+
<PtoVta>3</PtoVta>
|
8
|
+
<CbteTipo>1</CbteTipo>
|
9
|
+
<FchProceso>20110127</FchProceso>
|
10
|
+
<CantReg>2</CantReg>
|
11
|
+
<Resultado>A</Resultado>
|
12
|
+
<Reproceso>N</Reproceso>
|
13
|
+
</FeCabResp>
|
14
|
+
<FeDetResp>
|
15
|
+
<FECAEADetResponse>
|
16
|
+
<Concepto>1</Concepto>
|
17
|
+
<DocTipo>80</DocTipo>
|
18
|
+
<DocNro>30521189203</DocNro>
|
19
|
+
<CbteDesde>1</CbteDesde>
|
20
|
+
<CbteHasta>1</CbteHasta>
|
21
|
+
<CbteFch>20110201</CbteFch>
|
22
|
+
<Resultado>A</Resultado>
|
23
|
+
<CAEA>21043476341977</CAEA>
|
24
|
+
</FECAEADetResponse>
|
25
|
+
<FECAEADetResponse>
|
26
|
+
<Concepto>1</Concepto>
|
27
|
+
<DocTipo>80</DocTipo>
|
28
|
+
<DocNro>30521189203</DocNro>
|
29
|
+
<CbteDesde>2</CbteDesde>
|
30
|
+
<CbteHasta>2</CbteHasta>
|
31
|
+
<CbteFch>20110201</CbteFch>
|
32
|
+
<Resultado>R</Resultado>
|
33
|
+
<Observaciones>
|
34
|
+
<Obs>
|
35
|
+
<Code>724</Code>
|
36
|
+
<Msg>Msg</Msg>
|
37
|
+
</Obs>
|
38
|
+
</Observaciones>
|
39
|
+
<CAEA>21043476341977</CAEA>
|
40
|
+
</FECAEADetResponse>
|
41
|
+
</FeDetResp>
|
42
|
+
</FECAEARegInformativoResult>
|
43
|
+
</FECAEARegInformativoResponse>
|
44
|
+
</soap:Body>
|
45
|
+
</soap:Envelope>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FECAEASolicitarResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FECAEASolicitarResult>
|
5
|
+
<ResultGet>
|
6
|
+
<Periodo>0</Periodo>
|
7
|
+
<Orden>0</Orden>
|
8
|
+
</ResultGet>
|
9
|
+
<Errors>
|
10
|
+
<Err>
|
11
|
+
<Code>15008</Code>
|
12
|
+
<Msg>Existe un CAEA otorgado para la CUIT solicitante con el periodo y orden informado. Consultar el metodo FECAEAConsultar.</Msg>
|
13
|
+
</Err>
|
14
|
+
</Errors>
|
15
|
+
</FECAEASolicitarResult>
|
16
|
+
</FECAEASolicitarResponse>
|
17
|
+
</soap:Body>
|
18
|
+
</soap:Envelope>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<soap:Body>
|
3
|
+
<FECAEASolicitarResponse xmlns="http://ar.gov.afip.dif.FEV1/">
|
4
|
+
<FECAEASolicitarResult>
|
5
|
+
<ResultGet>
|
6
|
+
<CAEA>21043476341977</CAEA>
|
7
|
+
<Periodo>201102</Periodo>
|
8
|
+
<Orden>1</Orden>
|
9
|
+
<FchVigDesde>20110201</FchVigDesde>
|
10
|
+
<FchVigHasta>20110215</FchVigHasta>
|
11
|
+
<FchTopeInf>20110317</FchTopeInf>
|
12
|
+
<FchProceso>20110127124928</FchProceso>
|
13
|
+
</ResultGet>
|
14
|
+
</FECAEASolicitarResult>
|
15
|
+
</FECAEASolicitarResponse>
|
16
|
+
</soap:Body>
|
17
|
+
</soap:Envelope>
|
data/spec/manual/test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../lib')))
|
2
|
+
require 'afipws'
|
3
|
+
|
4
|
+
Savon.configure { |config| config.log = true }
|
5
|
+
|
6
|
+
ws = Afipws::WSFE.new :env => :development, :cuit => '20300032673',
|
7
|
+
:cert => File.read(File.dirname(__FILE__) + '/test.crt'),
|
8
|
+
:key => File.read(File.dirname(__FILE__) + '/test.key')
|
9
|
+
|
10
|
+
def obtener_ta ws
|
11
|
+
ws.cotizacion 'DOL'
|
12
|
+
xml = Builder::XmlMarkup.new indent: 2
|
13
|
+
xml.ar :Auth do
|
14
|
+
xml.ar :Token, ws.ta[:token]
|
15
|
+
xml.ar :Sign, ws.ta[:sign]
|
16
|
+
xml.ar :Cuit, ws.cuit
|
17
|
+
end
|
18
|
+
puts xml.target!
|
19
|
+
end
|
20
|
+
|
21
|
+
def autorizar_comprobante ws
|
22
|
+
ultimo = ws.ultimo_comprobante_autorizado :pto_vta => 1, :cbte_tipo => 1
|
23
|
+
# cant_informar = ws.cant_max_registros_x_request
|
24
|
+
cant_informar = 2
|
25
|
+
puts "Informando #{cant_informar} comprobantes"
|
26
|
+
comprobantes = (1..cant_informar).to_a.map do |i|
|
27
|
+
{
|
28
|
+
:cbte_nro => ultimo + i, :concepto => 1, :doc_nro => 30521189203, :doc_tipo => 80, :cbte_fch => Date.today,
|
29
|
+
:imp_total => 1270.48, :imp_neto => 1049.98, :imp_iva => 220.50, :mon_id => 'PES', :mon_cotiz => 1,
|
30
|
+
:iva => { :alic_iva => [{ :id => 5, :base_imp => 1049.98, :importe => 220.50 }]}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
puts ws.autorizar_comprobantes(:cbte_tipo => 1, :pto_vta => 1, :comprobantes => comprobantes)
|
34
|
+
end
|
35
|
+
|
36
|
+
def consultar_caea ws
|
37
|
+
ws.consultar_caea Date.new(2011,2,3)
|
38
|
+
end
|
39
|
+
|
40
|
+
def soap_actions ws
|
41
|
+
ws.client.soap_actions
|
42
|
+
end
|
43
|
+
|
44
|
+
p ws.tipos_comprobantes
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 0
|
8
7
|
- 1
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Emmanuel Nicolau
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-31 00:00:00 -03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -108,6 +108,32 @@ dependencies:
|
|
108
108
|
type: :runtime
|
109
109
|
prerelease: false
|
110
110
|
version_requirements: *id007
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: i18n
|
113
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
type: :runtime
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *id008
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: httpclient
|
126
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: *id009
|
111
137
|
description: ""
|
112
138
|
email:
|
113
139
|
- emmanicolau@gmail.com
|
@@ -118,6 +144,7 @@ extensions: []
|
|
118
144
|
extra_rdoc_files: []
|
119
145
|
|
120
146
|
files:
|
147
|
+
- .autotest
|
121
148
|
- .gitignore
|
122
149
|
- .rspec
|
123
150
|
- .rvmrc
|
@@ -135,7 +162,6 @@ files:
|
|
135
162
|
- lib/afipws/wsaa.rb
|
136
163
|
- lib/afipws/wsfe.rb
|
137
164
|
- lib/core_ext/hash.rb
|
138
|
-
- lib/core_ext/string.rb
|
139
165
|
- spec/afipws/test.crt
|
140
166
|
- spec/afipws/test.key
|
141
167
|
- spec/afipws/type_conversions_spec.rb
|
@@ -148,6 +174,7 @@ files:
|
|
148
174
|
- spec/fixtures/fe_dummy/success.xml
|
149
175
|
- spec/fixtures/fe_param_get_cotizacion/dolar.xml
|
150
176
|
- spec/fixtures/fe_param_get_cotizacion/inexistente.xml
|
177
|
+
- spec/fixtures/fe_param_get_ptos_venta/success.xml
|
151
178
|
- spec/fixtures/fe_param_get_tipos_cbte/failure_1_error.xml
|
152
179
|
- spec/fixtures/fe_param_get_tipos_cbte/failure_2_errors.xml
|
153
180
|
- spec/fixtures/fe_param_get_tipos_cbte/success.xml
|
@@ -157,15 +184,19 @@ files:
|
|
157
184
|
- spec/fixtures/fe_param_get_tipos_tributos/success.xml
|
158
185
|
- spec/fixtures/fecae_solicitar/autorizacion_1_cbte.xml
|
159
186
|
- spec/fixtures/fecae_solicitar/autorizacion_2_cbtes.xml
|
160
|
-
- spec/fixtures/fecae_solicitar/
|
187
|
+
- spec/fixtures/fecae_solicitar/dos_observaciones.xml
|
188
|
+
- spec/fixtures/fecae_solicitar/una_observacion.xml
|
189
|
+
- spec/fixtures/fecaea_consultar/success.xml
|
190
|
+
- spec/fixtures/fecaea_reg_informativo/informe_rtdo_parcial.xml
|
191
|
+
- spec/fixtures/fecaea_solicitar/caea_ya_otorgado.xml
|
192
|
+
- spec/fixtures/fecaea_solicitar/success.xml
|
161
193
|
- spec/fixtures/login_cms/fault.xml
|
162
194
|
- spec/fixtures/login_cms/success.xml
|
163
195
|
- spec/fixtures/login_cms/token_expirado.xml
|
164
196
|
- spec/fixtures/wsaa.wsdl
|
165
197
|
- spec/fixtures/wsfe.wsdl
|
166
|
-
- spec/manual/autorizar_comprobante.rb
|
167
198
|
- spec/manual/generar_keys.txt
|
168
|
-
- spec/manual/
|
199
|
+
- spec/manual/test.rb
|
169
200
|
- spec/spec_helper.rb
|
170
201
|
- spec/support/matchers.rb
|
171
202
|
has_rdoc: true
|
@@ -182,7 +213,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
182
213
|
requirements:
|
183
214
|
- - ">="
|
184
215
|
- !ruby/object:Gem::Version
|
185
|
-
hash:
|
216
|
+
hash: -619404093067996403
|
186
217
|
segments:
|
187
218
|
- 0
|
188
219
|
version: "0"
|
@@ -191,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
222
|
requirements:
|
192
223
|
- - ">="
|
193
224
|
- !ruby/object:Gem::Version
|
194
|
-
hash:
|
225
|
+
hash: -619404093067996403
|
195
226
|
segments:
|
196
227
|
- 0
|
197
228
|
version: "0"
|
@@ -215,6 +246,7 @@ test_files:
|
|
215
246
|
- spec/fixtures/fe_dummy/success.xml
|
216
247
|
- spec/fixtures/fe_param_get_cotizacion/dolar.xml
|
217
248
|
- spec/fixtures/fe_param_get_cotizacion/inexistente.xml
|
249
|
+
- spec/fixtures/fe_param_get_ptos_venta/success.xml
|
218
250
|
- spec/fixtures/fe_param_get_tipos_cbte/failure_1_error.xml
|
219
251
|
- spec/fixtures/fe_param_get_tipos_cbte/failure_2_errors.xml
|
220
252
|
- spec/fixtures/fe_param_get_tipos_cbte/success.xml
|
@@ -224,14 +256,18 @@ test_files:
|
|
224
256
|
- spec/fixtures/fe_param_get_tipos_tributos/success.xml
|
225
257
|
- spec/fixtures/fecae_solicitar/autorizacion_1_cbte.xml
|
226
258
|
- spec/fixtures/fecae_solicitar/autorizacion_2_cbtes.xml
|
227
|
-
- spec/fixtures/fecae_solicitar/
|
259
|
+
- spec/fixtures/fecae_solicitar/dos_observaciones.xml
|
260
|
+
- spec/fixtures/fecae_solicitar/una_observacion.xml
|
261
|
+
- spec/fixtures/fecaea_consultar/success.xml
|
262
|
+
- spec/fixtures/fecaea_reg_informativo/informe_rtdo_parcial.xml
|
263
|
+
- spec/fixtures/fecaea_solicitar/caea_ya_otorgado.xml
|
264
|
+
- spec/fixtures/fecaea_solicitar/success.xml
|
228
265
|
- spec/fixtures/login_cms/fault.xml
|
229
266
|
- spec/fixtures/login_cms/success.xml
|
230
267
|
- spec/fixtures/login_cms/token_expirado.xml
|
231
268
|
- spec/fixtures/wsaa.wsdl
|
232
269
|
- spec/fixtures/wsfe.wsdl
|
233
|
-
- spec/manual/autorizar_comprobante.rb
|
234
270
|
- spec/manual/generar_keys.txt
|
235
|
-
- spec/manual/
|
271
|
+
- spec/manual/test.rb
|
236
272
|
- spec/spec_helper.rb
|
237
273
|
- spec/support/matchers.rb
|
data/lib/core_ext/string.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../lib')))
|
2
|
-
require 'afipws'
|
3
|
-
|
4
|
-
Savon.configure { |config| config.log = true }
|
5
|
-
|
6
|
-
ws = Afipws::WSFE.new :env => :dev, :cuit => '20300032673',
|
7
|
-
:cert => File.read(File.dirname(__FILE__) + '/test.crt'),
|
8
|
-
:key => File.read(File.dirname(__FILE__) + '/test.key')
|
9
|
-
|
10
|
-
ultimo = ws.ultimo_comprobante_autorizado :pto_vta => 1, :cbte_tipo => 1
|
11
|
-
puts ws.autorizar_comprobantes(:cbte_tipo => 1, :pto_vta => 1, :comprobantes => [
|
12
|
-
{
|
13
|
-
:cbte_nro => ultimo + 1, :concepto => 1, :doc_nro => 30521189203, :doc_tipo => 80, :cbte_fch => Date.new(2011,01,13),
|
14
|
-
:imp_total => 1270.48, :imp_neto => 1049.98, :imp_iva => 220.50, :mon_id => 'PES', :mon_cotiz => 1,
|
15
|
-
:iva => { :alic_iva => [{ :id => 5, :base_imp => 1049.98, :importe => 220.50 }]}
|
16
|
-
},
|
17
|
-
{
|
18
|
-
:cbte_nro => ultimo + 2, :concepto => 1, :doc_nro => 30521189203, :doc_tipo => 80, :cbte_fch => Date.new(2011,01,13),
|
19
|
-
:imp_total => 1270.48, :imp_neto => 1049.98, :imp_iva => 220.50, :mon_id => 'PES', :mon_cotiz => 1,
|
20
|
-
:iva => { :alic_iva => [{ :id => 5, :base_imp => 1049.98, :importe => 220.60 }]}
|
21
|
-
}
|
22
|
-
])
|
data/spec/manual/obtener_ta.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../lib')))
|
2
|
-
require 'afipws'
|
3
|
-
|
4
|
-
Savon.configure { |config| config.log = true }
|
5
|
-
|
6
|
-
ws = Afipws::WSFE.new :env => :dev, :cuit => '20300032673',
|
7
|
-
:cert => File.read(File.dirname(__FILE__) + '/test.crt'),
|
8
|
-
:key => File.read(File.dirname(__FILE__) + '/test.key')
|
9
|
-
|
10
|
-
puts ws.cotizacion 'DOL'
|
11
|
-
|
12
|
-
xml = Builder::XmlMarkup.new indent: 2
|
13
|
-
xml.ar :Auth do
|
14
|
-
xml.ar :Token, ws.ta[:token]
|
15
|
-
xml.ar :Sign, ws.ta[:sign]
|
16
|
-
xml.ar :Cuit, ws.cuit
|
17
|
-
end
|
18
|
-
puts xml.target!
|