afipws 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +75 -25
- data/Guardfile +0 -16
- data/afipws.gemspec +6 -5
- data/lib/afipws.rb +0 -5
- data/lib/afipws/client.rb +5 -30
- data/lib/afipws/core_ext/hash.rb +0 -12
- data/lib/afipws/version.rb +1 -1
- data/lib/afipws/wsaa.rb +3 -3
- data/lib/afipws/wsfe.rb +2 -1
- data/spec/afipws/core_ext/hash_spec.rb +1 -22
- data/spec/afipws/type_conversions_spec.rb +1 -1
- data/spec/afipws/wsaa_spec.rb +5 -6
- data/spec/afipws/wsfe_spec.rb +147 -147
- data/spec/manual/test.rb +6 -12
- data/spec/spec_helper.rb +16 -3
- data/spec/support/matchers.rb +6 -32
- data/spec/support/savon_extensions.rb +39 -0
- metadata +43 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0430f1994cf2d6f6afe098bda447441df15f7bb
|
4
|
+
data.tar.gz: 519d1e3e5ea15497d131905c9b1e37e2959b26b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fa823ccd4f74a535dce9893b9df3277a82f944789e8c75be937c4fc277afc32fdc6e9136359b13fab08c839b063a0bc71b34a89053eb448c3bc654babc5f756
|
7
|
+
data.tar.gz: 9a40c8d4855d4b0d5eb3ea0112c38f282213ecf727f1a3963026670fcd3f76f2fd433a535140eb7ae0a9d53b7011e20fad172e812e83095195c630608d3969f4
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
afipws (0.
|
4
|
+
afipws (1.0.0)
|
5
5
|
activesupport
|
6
6
|
builder
|
7
7
|
httpclient
|
8
|
-
httpi (>= 2.4.2)
|
9
8
|
i18n
|
10
9
|
nokogiri
|
11
|
-
savon
|
10
|
+
savon (~> 2.11.0)
|
12
11
|
|
13
12
|
GEM
|
14
13
|
remote: http://rubygems.org/
|
@@ -18,57 +17,108 @@ GEM
|
|
18
17
|
i18n (~> 0.7)
|
19
18
|
minitest (~> 5.1)
|
20
19
|
tzinfo (~> 1.1)
|
21
|
-
|
20
|
+
akami (1.3.1)
|
21
|
+
gyoku (>= 0.4.0)
|
22
|
+
nokogiri
|
23
|
+
builder (3.2.2)
|
24
|
+
byebug (1.1.1)
|
25
|
+
columnize (~> 0.3.6)
|
26
|
+
debugger-linecache (~> 1.2.0)
|
27
|
+
coderay (1.1.1)
|
28
|
+
columnize (0.3.6)
|
22
29
|
concurrent-ruby (1.0.2)
|
23
|
-
|
24
|
-
diff-lcs (1.
|
25
|
-
|
30
|
+
debugger-linecache (1.2.0)
|
31
|
+
diff-lcs (1.2.5)
|
32
|
+
ffi (1.9.14)
|
33
|
+
formatador (0.2.5)
|
34
|
+
guard (2.14.0)
|
35
|
+
formatador (>= 0.2.4)
|
36
|
+
listen (>= 2.7, < 4.0)
|
37
|
+
lumberjack (~> 1.0)
|
38
|
+
nenv (~> 0.1)
|
39
|
+
notiffany (~> 0.0)
|
40
|
+
pry (>= 0.9.12)
|
41
|
+
shellany (~> 0.0)
|
42
|
+
thor (>= 0.18.1)
|
43
|
+
guard-rspec (4.3.1)
|
44
|
+
guard (~> 2.1)
|
45
|
+
rspec (>= 2.14, < 4.0)
|
46
|
+
gyoku (1.3.1)
|
26
47
|
builder (>= 2.1.2)
|
27
48
|
httpclient (2.8.2.4)
|
28
49
|
httpi (2.4.2)
|
29
50
|
rack
|
30
51
|
socksify
|
31
52
|
i18n (0.7.0)
|
53
|
+
listen (3.1.5)
|
54
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
55
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
56
|
+
ruby_dep (~> 1.2)
|
57
|
+
lumberjack (1.0.10)
|
58
|
+
method_source (0.8.2)
|
32
59
|
mini_portile2 (2.1.0)
|
33
60
|
minitest (5.9.1)
|
34
61
|
mocha (0.9.10)
|
35
62
|
rake
|
63
|
+
nenv (0.3.0)
|
36
64
|
nokogiri (1.6.8)
|
37
65
|
mini_portile2 (~> 2.1.0)
|
38
66
|
pkg-config (~> 1.1.7)
|
67
|
+
nori (2.6.0)
|
68
|
+
notiffany (0.1.1)
|
69
|
+
nenv (~> 0.1)
|
70
|
+
shellany (~> 0.0)
|
39
71
|
pkg-config (1.1.7)
|
72
|
+
pry (0.10.4)
|
73
|
+
coderay (~> 1.1.0)
|
74
|
+
method_source (~> 0.8.1)
|
75
|
+
slop (~> 3.4)
|
76
|
+
pry-byebug (1.0.1)
|
77
|
+
byebug (~> 1.1.1)
|
78
|
+
pry (>= 0.9.10)
|
40
79
|
rack (2.0.1)
|
41
80
|
rake (10.4.2)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
rspec-
|
50
|
-
|
81
|
+
rb-fsevent (0.9.7)
|
82
|
+
rb-inotify (0.9.7)
|
83
|
+
ffi (>= 0.5.0)
|
84
|
+
rspec (2.14.1)
|
85
|
+
rspec-core (~> 2.14.0)
|
86
|
+
rspec-expectations (~> 2.14.0)
|
87
|
+
rspec-mocks (~> 2.14.0)
|
88
|
+
rspec-core (2.14.8)
|
89
|
+
rspec-expectations (2.14.5)
|
90
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
91
|
+
rspec-mocks (2.14.6)
|
92
|
+
ruby_dep (1.4.0)
|
93
|
+
savon (2.11.1)
|
94
|
+
akami (~> 1.2)
|
51
95
|
builder (>= 2.1.2)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
96
|
+
gyoku (~> 1.2)
|
97
|
+
httpi (~> 2.3)
|
98
|
+
nokogiri (>= 1.4.0)
|
99
|
+
nori (~> 2.4)
|
100
|
+
wasabi (~> 3.4)
|
101
|
+
shellany (0.0.1)
|
102
|
+
slop (3.6.0)
|
59
103
|
socksify (1.7.0)
|
104
|
+
thor (0.19.1)
|
60
105
|
thread_safe (0.3.5)
|
61
106
|
tzinfo (1.2.2)
|
62
107
|
thread_safe (~> 0.1)
|
108
|
+
wasabi (3.5.0)
|
109
|
+
httpi (~> 2.0)
|
110
|
+
nokogiri (>= 1.4.2)
|
63
111
|
|
64
112
|
PLATFORMS
|
65
113
|
ruby
|
66
114
|
|
67
115
|
DEPENDENCIES
|
68
116
|
afipws!
|
117
|
+
guard-rspec (~> 4.3.1)
|
118
|
+
mocha (~> 0.9.10)
|
119
|
+
pry-byebug
|
69
120
|
rake (~> 10.4.2)
|
70
|
-
rspec
|
71
|
-
savon_spec
|
121
|
+
rspec (~> 2.14.1)
|
72
122
|
|
73
123
|
BUNDLED WITH
|
74
124
|
1.12.3
|
data/Guardfile
CHANGED
@@ -1,19 +1,3 @@
|
|
1
|
-
# A sample Guardfile
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
3
|
-
|
4
|
-
## Uncomment and set this to only include directories you want to watch
|
5
|
-
# directories %w(app lib config test spec features) \
|
6
|
-
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
-
|
8
|
-
## Note: if you are using the `directories` clause above and you are not
|
9
|
-
## watching the project directory ('.'), then you will want to move
|
10
|
-
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
-
#
|
12
|
-
# $ mkdir config
|
13
|
-
# $ mv Guardfile config/
|
14
|
-
# $ ln -s config/Guardfile .
|
15
|
-
#
|
16
|
-
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
1
|
guard :rspec, cmd: 'rspec' do
|
18
2
|
watch(%r{^spec/.+_spec\.rb$})
|
19
3
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
data/afipws.gemspec
CHANGED
@@ -18,14 +18,15 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_development_dependency
|
22
|
-
s.add_development_dependency
|
23
|
-
s.add_development_dependency
|
21
|
+
s.add_development_dependency 'rspec', '~> 2.14.1'
|
22
|
+
s.add_development_dependency 'rake', '~> 10.4.2'
|
23
|
+
s.add_development_dependency 'mocha', '~> 0.9.10'
|
24
|
+
s.add_development_dependency 'guard-rspec', '~> 4.3.1'
|
25
|
+
s.add_development_dependency 'pry-byebug'
|
24
26
|
s.add_dependency "builder"
|
25
|
-
s.add_dependency "savon"
|
27
|
+
s.add_dependency "savon", '~> 2.11.0'
|
26
28
|
s.add_dependency "nokogiri"
|
27
29
|
s.add_dependency "activesupport"
|
28
30
|
s.add_dependency "i18n"
|
29
31
|
s.add_dependency "httpclient"
|
30
|
-
s.add_dependency "httpi", '>= 2.4.2'
|
31
32
|
end
|
data/lib/afipws.rb
CHANGED
data/lib/afipws/client.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
module Afipws
|
2
2
|
class Client
|
3
|
-
def initialize
|
4
|
-
@client = Savon
|
5
|
-
wsdl.document = wsdl_url
|
6
|
-
http.auth.ssl.verify_mode = :none if env == :development # Esto está porque el certificado del WSAA había vencido durante las pruebas
|
7
|
-
http.auth.ssl.ssl_version = :SSLv3 if env == :development || Date.today >= Date.new(2016,11,1) # Esto es porque la afip cambió el algoritmo de cifrado de los certificados y sin esto no conectaba al WSFE. En el entorno de homologación ya está realizado el cambio pero en production recién el 1/11/2016.
|
8
|
-
end
|
3
|
+
def initialize savon_options
|
4
|
+
@client = Savon.client savon_options.reverse_merge(soap_version: 2)
|
9
5
|
end
|
10
6
|
|
11
7
|
def request action, body = nil
|
@@ -18,36 +14,15 @@ module Afipws
|
|
18
14
|
end
|
19
15
|
|
20
16
|
def raw_request action, body = nil
|
21
|
-
@client.
|
17
|
+
@client.call action, message: body
|
22
18
|
end
|
23
19
|
|
24
|
-
def
|
25
|
-
@client.
|
20
|
+
def operations
|
21
|
+
@client.operations
|
26
22
|
end
|
27
23
|
|
28
24
|
def method_missing method_sym, *args
|
29
25
|
request method_sym, *args
|
30
26
|
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def add_ns_to_keys body
|
35
|
-
case body
|
36
|
-
when Hash
|
37
|
-
Hash[body.map { |k, v| ["#{namespace}:#{camelize(k)}", add_ns_to_keys(v)] }]
|
38
|
-
when Array
|
39
|
-
body.map { |x| add_ns_to_keys x }
|
40
|
-
else
|
41
|
-
body
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def namespace
|
46
|
-
:wsdl
|
47
|
-
end
|
48
|
-
|
49
|
-
def camelize k
|
50
|
-
k.is_a?(String) ? k : k.to_s.camelize
|
51
|
-
end
|
52
27
|
end
|
53
28
|
end
|
data/lib/afipws/core_ext/hash.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
module Afipws
|
2
2
|
module CoreExt
|
3
3
|
module Hash
|
4
|
-
def fetch_path path
|
5
|
-
path.split('/').drop(1).inject(self) do |hash, key|
|
6
|
-
if scan = key.scan(/\[[\d+]\]/).first
|
7
|
-
key.sub! scan, ''
|
8
|
-
idx = scan.scan(/\d+/).first.to_i
|
9
|
-
hash.respond_to?(:has_key?) && hash.has_key?(key) ? hash[key][idx] : break
|
10
|
-
else
|
11
|
-
hash.respond_to?(:has_key?) && hash.has_key?(key) ? hash[key] : break
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
4
|
def select_keys *keys
|
17
5
|
select { |k, _| keys.include? k }
|
18
6
|
end
|
data/lib/afipws/version.rb
CHANGED
data/lib/afipws/wsaa.rb
CHANGED
@@ -15,7 +15,7 @@ module Afipws
|
|
15
15
|
@service = options[:service] || 'wsfe'
|
16
16
|
@ttl = options[:ttl] || 2400
|
17
17
|
@cuit = options[:cuit]
|
18
|
-
@client = Client.new WSDL[@env]
|
18
|
+
@client = Client.new Hash(options[:savon]).reverse_merge(wsdl: WSDL[@env])
|
19
19
|
end
|
20
20
|
|
21
21
|
def generar_tra service, ttl
|
@@ -47,12 +47,12 @@ module Afipws
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def login
|
50
|
-
response = @client.raw_request :login_cms,
|
50
|
+
response = @client.raw_request :login_cms, in0: tra(@key, @cert, @service, @ttl)
|
51
51
|
ta = Nokogiri::XML(Nokogiri::XML(response.to_xml).text)
|
52
52
|
{ token: ta.css('token').text, sign: ta.css('sign').text,
|
53
53
|
generation_time: from_xsd_datetime(ta.css('generationTime').text),
|
54
54
|
expiration_time: from_xsd_datetime(ta.css('expirationTime').text) }
|
55
|
-
rescue Savon::
|
55
|
+
rescue Savon::SOAPFault => f
|
56
56
|
raise WSError, f.message
|
57
57
|
end
|
58
58
|
|
data/lib/afipws/wsfe.rb
CHANGED
@@ -15,7 +15,8 @@ module Afipws
|
|
15
15
|
def initialize options = {}
|
16
16
|
@env = (options[:env] || :test).to_sym
|
17
17
|
@wsaa = options[:wsaa] || WSAA.new(options.merge(service: 'wsfe'))
|
18
|
-
|
18
|
+
ssl_version = env == :development || Date.today >= Date.new(2016,11,1) ? :SSLv3 : :TLSv1
|
19
|
+
@client = Client.new Hash(options[:savon]).reverse_merge(wsdl: WSDL[@env], ssl_version: ssl_version, convert_request_keys_to: :camelcase)
|
19
20
|
end
|
20
21
|
|
21
22
|
def dummy
|
@@ -1,27 +1,6 @@
|
|
1
|
-
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Hash do
|
5
|
-
context "fetch_path" do
|
6
|
-
it "deberia aceptar un path como /../.. y retornar el value" do
|
7
|
-
hash = { '1' => 2, '3' => { '4' => '5', '6' => { '7' => '8' } } }
|
8
|
-
hash.fetch_path('/1').should == 2
|
9
|
-
hash.fetch_path('/1/2').should == nil
|
10
|
-
hash.fetch_path('/2').should == nil
|
11
|
-
hash.fetch_path('/3/4').should == '5'
|
12
|
-
hash.fetch_path('/3/6').should == { '7' => '8' }
|
13
|
-
hash.fetch_path('/3/6/7').should == '8'
|
14
|
-
end
|
15
|
-
|
16
|
-
it "debería permitir acceder a values tipo array con subindice" do
|
17
|
-
hash = { '1' => [{ '2' => 3 }, { '4' => 5 }] }
|
18
|
-
hash.fetch_path('/1[0]/2').should == 3
|
19
|
-
hash.fetch_path('/1[1]/4').should == 5
|
20
|
-
hash.fetch_path('/1[0]').should == { '2' => 3 }
|
21
|
-
hash.fetch_path('/1[2]').should == nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
4
|
context "select_keys" do
|
26
5
|
it "debería tomar los values de las keys indicadas" do
|
27
6
|
hash = Hash[1, 2, 3, 4]
|
data/spec/afipws/wsaa_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Afipws::WSAA do
|
5
4
|
context "generación documento tra" do
|
@@ -30,9 +29,9 @@ describe Afipws::WSAA do
|
|
30
29
|
|
31
30
|
context "login" do
|
32
31
|
it "debería mandar el TRA al WS y obtener el TA" do
|
33
|
-
ws = Afipws::WSAA.new :
|
32
|
+
ws = Afipws::WSAA.new key: 'key', cert: 'cert'
|
34
33
|
ws.expects(:tra).with('key', 'cert', 'wsfe', 2400).returns('tra')
|
35
|
-
savon.expects(
|
34
|
+
savon.expects(:login_cms).with(message: {in0: 'tra'}).returns(fixture('login_cms/success'))
|
36
35
|
ta = ws.login
|
37
36
|
ta[:token].should == 'PD94='
|
38
37
|
ta[:sign].should == 'i9xDN='
|
@@ -42,8 +41,8 @@ describe Afipws::WSAA do
|
|
42
41
|
|
43
42
|
it "debería encapsular SOAP Faults" do
|
44
43
|
subject.stubs(:tra).returns('')
|
45
|
-
savon.
|
46
|
-
|
44
|
+
savon.expects(:login_cms).with(message: :any).returns(fixture('login_cms/fault'))
|
45
|
+
lambda { subject.login }.should raise_error Afipws::WSError, /CMS no es valido/
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
data/spec/afipws/wsfe_spec.rb
CHANGED
@@ -1,223 +1,222 @@
|
|
1
|
-
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Afipws::WSFE do
|
5
|
-
let :
|
6
|
-
|
7
|
-
wsaa.stubs :login => { :token => 't', :sign => 's', :expiration_time => 12.hours.from_now }
|
8
|
-
Afipws::WSFE.new :cuit => '1', :wsaa => wsaa
|
9
|
-
end
|
4
|
+
let(:auth) { {auth: {token: 't', sign: 's', expiration_time: 12.hours.from_now}} }
|
5
|
+
let(:ws) { Afipws::WSFE.new cuit: '1', wsaa: Afipws::WSAA.new.tap { |wsaa| wsaa.stubs auth: auth } }
|
10
6
|
|
11
7
|
context "Métodos de negocio" do
|
12
8
|
it "dummy" do
|
13
|
-
savon.expects(
|
14
|
-
ws.dummy.should == { :
|
9
|
+
savon.expects(:fe_dummy).returns(fixture('fe_dummy/success'))
|
10
|
+
ws.dummy.should == { app_server: "OK", db_server: "OK", auth_server: "OK" }
|
15
11
|
end
|
16
12
|
|
17
13
|
it "tipos_comprobantes" do
|
18
|
-
savon.expects(
|
14
|
+
savon.expects(:fe_param_get_tipos_cbte).with(message: auth).returns(fixture('fe_param_get_tipos_cbte/success'))
|
19
15
|
ws.tipos_comprobantes.should == [
|
20
|
-
{ :
|
21
|
-
{ :
|
16
|
+
{ id: 1, desc: "Factura A", fch_desde: Date.new(2010,9,17), fch_hasta: nil },
|
17
|
+
{ id: 2, desc: "Nota de Débito A", fch_desde: Date.new(2010,9,18), fch_hasta: Date.new(2011,9,18) }]
|
22
18
|
end
|
23
19
|
|
24
20
|
it "tipos_documentos" do
|
25
|
-
savon.expects(
|
26
|
-
ws.tipos_documentos.should == [{ :
|
21
|
+
savon.expects(:fe_param_get_tipos_doc).with(message: auth).returns(fixture('fe_param_get_tipos_doc/success'))
|
22
|
+
ws.tipos_documentos.should == [{ id: 80, desc: "CUIT", fch_desde: Date.new(2008,7,25), fch_hasta: nil }]
|
27
23
|
end
|
28
24
|
|
29
25
|
it "tipos_monedas" do
|
30
|
-
savon.expects(
|
26
|
+
savon.expects(:fe_param_get_tipos_monedas).with(message: auth).returns(fixture('fe_param_get_tipos_monedas/success'))
|
31
27
|
ws.tipos_monedas.should == [
|
32
|
-
{ :
|
33
|
-
{ :
|
28
|
+
{ id: 'PES', desc: "Pesos Argentinos", fch_desde: Date.new(2009,4,3), fch_hasta: nil },
|
29
|
+
{ id: '002', desc: "Dólar Libre EEUU", fch_desde: Date.new(2009,4,16), fch_hasta: nil }]
|
34
30
|
end
|
35
31
|
|
36
32
|
it "tipos_iva" do
|
37
|
-
savon.expects(
|
38
|
-
ws.tipos_iva.should == [{ :
|
33
|
+
savon.expects(:fe_param_get_tipos_iva).with(message: auth).returns(fixture('fe_param_get_tipos_iva/success'))
|
34
|
+
ws.tipos_iva.should == [{ id: 5, desc: "21%", fch_desde: Date.new(2009,2,20), fch_hasta: nil }]
|
39
35
|
end
|
40
36
|
|
41
37
|
it "tipos_tributos" do
|
42
|
-
savon.expects(
|
43
|
-
ws.tipos_tributos.should == [{ :
|
38
|
+
savon.expects(:fe_param_get_tipos_tributos).with(message: auth).returns(fixture('fe_param_get_tipos_tributos/success'))
|
39
|
+
ws.tipos_tributos.should == [{ id: 2, desc: "Impuestos provinciales", fch_desde: Date.new(2010,9,17), fch_hasta: nil }]
|
44
40
|
end
|
45
41
|
|
46
42
|
it "puntos_venta" do
|
47
|
-
savon.expects(
|
43
|
+
savon.expects(:fe_param_get_ptos_venta).with(message: auth).returns(fixture('fe_param_get_ptos_venta/success'))
|
48
44
|
ws.puntos_venta.should == [
|
49
|
-
{ :
|
50
|
-
{ :
|
51
|
-
]
|
45
|
+
{ nro: 1, emision_tipo: "CAE", bloqueado: false, fch_baja: nil },
|
46
|
+
{ nro: 2, emision_tipo: "CAEA", bloqueado: true, fch_baja: Date.new(2011,1,31) }]
|
52
47
|
end
|
53
48
|
|
54
49
|
context "cotizacion" do
|
55
50
|
it "cuando la moneda solicitada existe" do
|
56
|
-
savon.expects(
|
51
|
+
savon.expects(:fe_param_get_cotizacion).with(message: auth.merge(mon_id: 'DOL')).returns(fixture('fe_param_get_cotizacion/dolar'))
|
57
52
|
ws.cotizacion('DOL').should == 3.976
|
58
53
|
end
|
59
54
|
|
60
55
|
it "cuando la moneda no existe" do
|
61
|
-
savon.expects(
|
62
|
-
|
56
|
+
savon.expects(:fe_param_get_cotizacion).with(message: auth.merge(mon_id: 'PES')).returns(fixture('fe_param_get_cotizacion/inexistente'))
|
57
|
+
lambda { ws.cotizacion('PES') }.should raise_error Afipws::WSError, /602: Sin Resultados/
|
63
58
|
end
|
64
59
|
end
|
65
60
|
|
66
61
|
it "cant_max_registros_x_lote" do
|
67
|
-
savon.expects(
|
62
|
+
savon.expects(:fe_comp_tot_x_request).with(message: auth).returns(fixture('fe_comp_tot_x_request/success'))
|
68
63
|
ws.cant_max_registros_x_lote.should == 250
|
69
64
|
end
|
70
65
|
|
71
66
|
context "autorizar_comprobante" do
|
72
67
|
it "debería devolver un hash con el CAE y su fecha de vencimiento" do
|
73
|
-
savon.expects(
|
74
|
-
'/
|
75
|
-
'
|
76
|
-
'
|
77
|
-
'
|
78
|
-
'
|
79
|
-
'
|
80
|
-
'
|
81
|
-
'
|
82
|
-
'
|
83
|
-
'
|
84
|
-
'
|
85
|
-
'
|
86
|
-
'
|
87
|
-
'
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
68
|
+
savon.expects(:fecae_solicitar).with(message: has_path(
|
69
|
+
'//Auth/Token' => 't',
|
70
|
+
'//FeCAEReq/FeCabReq/CantReg' => 1,
|
71
|
+
'//FeCAEReq/FeCabReq/PtoVta' => 2,
|
72
|
+
'//FeCAEReq/FeCabReq/CbteTipo' => 1,
|
73
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/DocTipo' => 80,
|
74
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/DocNro' => 30521189203,
|
75
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/CbteFch' => 20110113,
|
76
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/ImpTotal' => 1270.48,
|
77
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/ImpIVA' => 220.5,
|
78
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[1]/Id' => 5,
|
79
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[1]/Importe' => 220.5,
|
80
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Tributos/Tributo[1]/Id' => 0,
|
81
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Tributos/Tributo[1]/BaseImp' => 150,
|
82
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Tributos/Tributo[1]/Alic' => 5.2,
|
83
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Tributos/Tributo[1]/Importe' => 7.8
|
84
|
+
)).returns(fixture('fecae_solicitar/autorizacion_1_cbte'))
|
85
|
+
rta = ws.autorizar_comprobantes(cbte_tipo: 1, pto_vta: 2, comprobantes: [{cbte_nro: 1, concepto: 1,
|
86
|
+
doc_nro: 30521189203, doc_tipo: 80, cbte_fch: Date.new(2011,01,13),
|
87
|
+
imp_total: 1270.48, imp_neto: 1049.98, imp_iva: 220.50, mon_id: 'PES', mon_cotiz: 1,
|
88
|
+
iva: { alic_iva: [{ id: 5, base_imp: 1049.98, importe: 220.50 }]},
|
89
|
+
tributos: { tributo: [{ id: 0, base_imp: 150, alic: 5.2, importe: 7.8 }] }
|
94
90
|
}])
|
95
|
-
rta[0].should have_entries :
|
96
|
-
:
|
97
|
-
rta.should
|
91
|
+
rta[0].should have_entries cae: '61023008595705', cae_fch_vto: Date.new(2011,01,23), cbte_nro: 1,
|
92
|
+
resultado: 'A', observaciones: []
|
93
|
+
rta.size.should == 1
|
98
94
|
end
|
99
95
|
|
100
96
|
it "con varias alicuotas iva" do
|
101
|
-
savon.expects(
|
102
|
-
'
|
103
|
-
'
|
104
|
-
'
|
105
|
-
'
|
106
|
-
|
107
|
-
ws.autorizar_comprobantes(:
|
108
|
-
{ :
|
109
|
-
{ :
|
97
|
+
savon.expects(:fecae_solicitar).with(message: has_path(
|
98
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[1]/Id' => 5,
|
99
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[1]/Importe' => 21,
|
100
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[2]/Id' => 4,
|
101
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/Iva/AlicIva[2]/Importe' => 5.25
|
102
|
+
)).returns(fixture('fecae_solicitar/autorizacion_1_cbte'))
|
103
|
+
ws.autorizar_comprobantes(cbte_tipo: 1, pto_vta: 2, comprobantes: [{iva: {alic_iva: [
|
104
|
+
{ id: 5, base_imp: 100, importe: 21 },
|
105
|
+
{ id: 4, base_imp: 50, importe: 5.25 }
|
110
106
|
]}}])
|
111
107
|
end
|
112
108
|
|
113
109
|
it "con varios comprobantes aprobados" do
|
114
|
-
savon.expects(
|
115
|
-
'
|
116
|
-
'
|
117
|
-
'
|
118
|
-
'
|
119
|
-
'
|
120
|
-
|
121
|
-
rta = ws.autorizar_comprobantes(:
|
122
|
-
|
123
|
-
]
|
124
|
-
rta[0].should have_entries :cbte_nro => 5, :cae => '61033008894096'
|
125
|
-
rta[1].should have_entries :cbte_nro => 6, :cae => '61033008894101'
|
110
|
+
savon.expects(:fecae_solicitar).with(message: has_path(
|
111
|
+
'//FeCAEReq/FeCabReq/CantReg' => 2,
|
112
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/CbteDesde' => 5,
|
113
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[1]/CbteHasta' => 5,
|
114
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[2]/CbteDesde' => 6,
|
115
|
+
'//FeCAEReq/FeDetReq/FECAEDetRequest[2]/CbteHasta' => 6,
|
116
|
+
)).returns(fixture('fecae_solicitar/autorizacion_2_cbtes'))
|
117
|
+
rta = ws.autorizar_comprobantes(cbte_tipo: 1, pto_vta: 2, comprobantes: [{ cbte_nro: 5 }, { cbte_nro: 6 }])
|
118
|
+
rta[0].should have_entries cbte_nro: 5, cae: '61033008894096'
|
119
|
+
rta[1].should have_entries cbte_nro: 6, cae: '61033008894101'
|
126
120
|
end
|
127
121
|
|
128
122
|
it "con 2 observaciones" do
|
129
|
-
savon.
|
130
|
-
rta = ws.autorizar_comprobantes :
|
131
|
-
rta[0].should have_entries :
|
132
|
-
{:
|
123
|
+
savon.expects(:fecae_solicitar).with(message: :any).returns(fixture 'fecae_solicitar/dos_observaciones')
|
124
|
+
rta = ws.autorizar_comprobantes comprobantes: []
|
125
|
+
rta[0].should have_entries cbte_nro: 3, cae: nil, resultado: 'R', observaciones: [
|
126
|
+
{code: 10048, msg: 'Msg 1'}, {code: 10018, msg: 'Msg 2'}]
|
133
127
|
end
|
134
128
|
|
135
129
|
it "con 1 observación" do
|
136
|
-
savon.
|
137
|
-
rta = ws.autorizar_comprobantes :
|
138
|
-
rta[0].should have_entries :
|
130
|
+
savon.expects(:fecae_solicitar).with(message: :any).returns(fixture 'fecae_solicitar/una_observacion')
|
131
|
+
rta = ws.autorizar_comprobantes comprobantes: []
|
132
|
+
rta[0].should have_entries observaciones: [{code: 10048, msg: 'Msg 1'}]
|
139
133
|
end
|
140
134
|
end
|
141
135
|
|
142
136
|
context "solicitar_caea" do
|
143
137
|
it "debería mandar automáticamente el período y orden" do
|
144
|
-
Date.stubs :
|
145
|
-
savon.expects(
|
146
|
-
ws.solicitar_caea.should have_entries :
|
147
|
-
:
|
138
|
+
Date.stubs today: Date.new(2011,1,27)
|
139
|
+
savon.expects(:fecaea_solicitar).with(message: has_path('//Periodo' => '201102', '//Orden' => 1)).returns(fixture 'fecaea_solicitar/success')
|
140
|
+
ws.solicitar_caea.should have_entries caea: '21043476341977', fch_tope_inf: Date.new(2011,03,17),
|
141
|
+
fch_vig_desde: Date.new(2011,02,01), fch_vig_hasta: Date.new(2011,02,15)
|
148
142
|
end
|
149
143
|
|
150
144
|
context "periodo_para_solicitud_caea" do
|
151
145
|
it "cuando estoy en la primer quincena" do
|
152
|
-
Date.stubs :
|
153
|
-
ws.periodo_para_solicitud_caea.should == { :
|
154
|
-
Date.stubs :
|
155
|
-
ws.periodo_para_solicitud_caea.should == { :
|
146
|
+
Date.stubs today: Date.new(2011,1,12)
|
147
|
+
ws.periodo_para_solicitud_caea.should == { periodo: '201101', orden: 2 }
|
148
|
+
Date.stubs today: Date.new(2011,1,15)
|
149
|
+
ws.periodo_para_solicitud_caea.should == { periodo: '201101', orden: 2 }
|
156
150
|
end
|
157
151
|
|
158
152
|
it "cuando estoy en la segunda quincena" do
|
159
|
-
Date.stubs :
|
160
|
-
ws.periodo_para_solicitud_caea.should == { :
|
161
|
-
Date.stubs :
|
162
|
-
ws.periodo_para_solicitud_caea.should == { :
|
153
|
+
Date.stubs today: Date.new(2011,1,16)
|
154
|
+
ws.periodo_para_solicitud_caea.should == { periodo: '201102', orden: 1 }
|
155
|
+
Date.stubs today: Date.new(2011,1,31)
|
156
|
+
ws.periodo_para_solicitud_caea.should == { periodo: '201102', orden: 1 }
|
163
157
|
end
|
164
158
|
end
|
165
159
|
|
166
160
|
it "cuando el caea ya fue otorgado debería consultarlo y devolverlo" do
|
167
|
-
Date.stubs :
|
168
|
-
savon.expects(
|
169
|
-
savon.expects(
|
170
|
-
ws.solicitar_caea.should have_entries :
|
161
|
+
Date.stubs today: Date.new(2011,1,27)
|
162
|
+
savon.expects(:fecaea_solicitar).with(message: has_path('//Periodo' => '201102', '//Orden' => 1)).returns(fixture 'fecaea_solicitar/caea_ya_otorgado')
|
163
|
+
savon.expects(:fecaea_consultar).with(message: has_path('//Periodo' => '201102', '//Orden' => 1)).returns(fixture 'fecaea_consultar/success')
|
164
|
+
ws.solicitar_caea.should have_entries caea: '21043476341977', fch_vig_desde: Date.new(2011,02,01)
|
171
165
|
end
|
172
166
|
|
173
167
|
it "cuando hay otro error debería burbujearlo" do
|
174
|
-
savon.expects(
|
175
|
-
|
168
|
+
savon.expects(:fecaea_solicitar).with(message: :any).returns(fixture 'fecaea_solicitar/error_distinto')
|
169
|
+
lambda { ws.solicitar_caea }.should raise_error Afipws::WSError, /15007/
|
176
170
|
end
|
177
171
|
end
|
178
172
|
|
179
173
|
it "informar_comprobantes_caea" do
|
180
|
-
savon.expects(
|
181
|
-
'/
|
182
|
-
'
|
183
|
-
'
|
184
|
-
'
|
185
|
-
'
|
186
|
-
'
|
187
|
-
'
|
188
|
-
'
|
189
|
-
'
|
190
|
-
|
191
|
-
|
192
|
-
|
174
|
+
savon.expects(:fecaea_reg_informativo).with(message: has_path(
|
175
|
+
'//Auth/Token' => 't',
|
176
|
+
'//FeCAEARegInfReq/FeCabReq/CantReg' => 2,
|
177
|
+
'//FeCAEARegInfReq/FeCabReq/PtoVta' => 3,
|
178
|
+
'//FeCAEARegInfReq/FeCabReq/CbteTipo' => 1,
|
179
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CbteDesde' => 1,
|
180
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CbteHasta' => 1,
|
181
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[1]/CAEA' => '21043476341977',
|
182
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[2]/CbteDesde' => 2,
|
183
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[2]/CbteHasta' => 2,
|
184
|
+
'//FeCAEARegInfReq/FeDetReq/FECAEADetRequest[2]/CAEA' => '21043476341977',
|
185
|
+
)).returns(fixture 'fecaea_reg_informativo/informe_rtdo_parcial')
|
186
|
+
rta = ws.informar_comprobantes_caea(cbte_tipo: 1, pto_vta: 3, comprobantes: [
|
187
|
+
{ cbte_nro: 1, caea: '21043476341977' }, { cbte_nro: 2, caea: '21043476341977' },
|
193
188
|
])
|
194
|
-
rta[0].should have_entries :
|
195
|
-
rta[1].should have_entries :
|
189
|
+
rta[0].should have_entries cbte_nro: 1, caea: '21043476341977', resultado: 'A', observaciones: []
|
190
|
+
rta[1].should have_entries cbte_nro: 2, caea: '21043476341977', resultado: 'R', observaciones: [{code: 724, msg: 'Msg'}]
|
196
191
|
end
|
197
192
|
|
198
193
|
it "informar_caea_sin_movimientos" do
|
199
|
-
savon.expects(
|
200
|
-
'/
|
194
|
+
savon.expects(:fecaea_sin_movimiento_informar).with(message: has_path(
|
195
|
+
'//Auth/Token' => 't',
|
196
|
+
'//PtoVta' => 4,
|
197
|
+
'//CAEA' => '21043476341977'
|
198
|
+
)).returns(fixture 'fecaea_sin_movimiento_informar/success')
|
201
199
|
rta = ws.informar_caea_sin_movimientos('21043476341977', 4)
|
202
|
-
rta.should have_entries :
|
200
|
+
rta.should have_entries caea: '21043476341977', resultado: 'A'
|
203
201
|
end
|
204
202
|
|
205
203
|
context "consultar_caea" do
|
206
204
|
it "consultar_caea" do
|
207
|
-
savon.expects(
|
208
|
-
ws.consultar_caea(Date.new(2011,1,1)).should have_entries :
|
205
|
+
savon.expects(:fecaea_consultar).with(message: has_path('//Periodo' => '201101', '//Orden' => 1)).returns(fixture 'fecaea_consultar/success')
|
206
|
+
ws.consultar_caea(Date.new(2011,1,1)).should have_entries caea: '21043476341977', fch_tope_inf: Date.new(2011,03,17)
|
209
207
|
end
|
210
208
|
end
|
211
209
|
|
212
210
|
it "ultimo_comprobante_autorizado" do
|
213
|
-
savon.expects(
|
214
|
-
ws.ultimo_comprobante_autorizado(:
|
211
|
+
savon.expects(:fe_comp_ultimo_autorizado).with(message: has_path('//PtoVta' => 1, '//CbteTipo' => 1)).returns(fixture 'fe_comp_ultimo_autorizado/success')
|
212
|
+
ws.ultimo_comprobante_autorizado(pto_vta: 1, cbte_tipo: 1).should == 20
|
215
213
|
end
|
216
214
|
|
217
215
|
it "consultar_comprobante" do
|
218
|
-
savon.expects(
|
219
|
-
'/FeCompConsReq/PtoVta' => 1, '
|
220
|
-
|
216
|
+
savon.expects(:fe_comp_consultar).with(message: has_path(
|
217
|
+
'//Auth/Token' => 't', '//FeCompConsReq/PtoVta' => 1, '//FeCompConsReq/CbteTipo' => 2, '//FeCompConsReq/CbteNro' => 3
|
218
|
+
)).returns(fixture 'fe_comp_consultar/success')
|
219
|
+
rta = ws.consultar_comprobante(pto_vta: 1, cbte_tipo: 2, cbte_nro: 3)
|
221
220
|
rta[:cod_autorizacion].should == '61023008595705'
|
222
221
|
rta[:emision_tipo].should == 'CAE'
|
223
222
|
end
|
@@ -225,48 +224,49 @@ describe Afipws::WSFE do
|
|
225
224
|
|
226
225
|
context "autenticacion" do
|
227
226
|
it "debería autenticarse usando el WSAA" do
|
228
|
-
wsfe = Afipws::WSFE.new :
|
227
|
+
wsfe = Afipws::WSFE.new cuit: '1', cert: 'cert', key: 'key'
|
229
228
|
wsfe.wsaa.cert.should == 'cert'
|
230
229
|
wsfe.wsaa.key.should == 'key'
|
231
230
|
wsfe.wsaa.service.should == 'wsfe'
|
232
|
-
wsfe.wsaa.expects(:login).returns({ :
|
233
|
-
savon.expects(
|
231
|
+
wsfe.wsaa.expects(:login).returns({ token: 't', sign: 's' })
|
232
|
+
savon.expects(:fe_param_get_tipos_cbte).with(message: has_path(
|
233
|
+
'//Auth/Token' => 't', '//Auth/Sign' => 's', '//Auth/Cuit' => '1'
|
234
|
+
)).returns(fixture 'fe_param_get_tipos_cbte/success')
|
234
235
|
wsfe.tipos_comprobantes
|
235
236
|
end
|
236
237
|
end
|
237
238
|
|
238
239
|
context "entorno" do
|
239
240
|
it "debería usar las url para development cuando el env es development" do
|
240
|
-
Afipws::Client.expects(:new).with(
|
241
|
-
Afipws::Client.expects(:new).with(
|
242
|
-
wsfe = Afipws::WSFE.new :
|
241
|
+
Afipws::Client.expects(:new).with(wsdl: 'https://wsaahomo.afip.gov.ar/ws/services/LoginCms?wsdl')
|
242
|
+
Afipws::Client.expects(:new).with(wsdl: 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL', ssl_version: :SSLv3, convert_request_keys_to: :camelcase)
|
243
|
+
wsfe = Afipws::WSFE.new env: :development
|
243
244
|
wsfe.env.should == :development
|
244
245
|
end
|
245
246
|
|
246
247
|
it "debería usar las url para production cuando el env es production" do
|
247
|
-
Afipws::Client.expects(:new).with(
|
248
|
-
|
249
|
-
Afipws::
|
250
|
-
wsfe = Afipws::WSFE.new :env => 'production'
|
248
|
+
Afipws::Client.expects(:new).with(wsdl: 'https://wsaa.afip.gov.ar/ws/services/LoginCms?wsdl')
|
249
|
+
Afipws::Client.expects(:new).with(has_entries wsdl: File.expand_path(File.dirname(__FILE__) + '/../../') + "/lib/afipws/wsfev1.wsdl")
|
250
|
+
wsfe = Afipws::WSFE.new env: 'production'
|
251
251
|
wsfe.env.should == :production
|
252
252
|
end
|
253
253
|
end
|
254
254
|
|
255
255
|
context "manejo de errores" do
|
256
256
|
it "cuando hay un error" do
|
257
|
-
savon.expects(
|
258
|
-
|
257
|
+
savon.expects(:fe_param_get_tipos_cbte).with(message: :any).returns(fixture 'fe_param_get_tipos_cbte/failure_1_error')
|
258
|
+
lambda { ws.tipos_comprobantes }.should raise_error { |e|
|
259
259
|
e.should be_a Afipws::WSError
|
260
|
-
e.errors.should == [{ :
|
260
|
+
e.errors.should == [{ code: "600", msg: "No se corresponden token con firma" }]
|
261
261
|
e.message.should == "600: No se corresponden token con firma"
|
262
262
|
}
|
263
263
|
end
|
264
264
|
|
265
265
|
it "cuando hay varios errores" do
|
266
|
-
savon.expects(
|
267
|
-
|
266
|
+
savon.expects(:fe_param_get_tipos_cbte).with(message: :any).returns(fixture 'fe_param_get_tipos_cbte/failure_2_errors')
|
267
|
+
lambda { ws.tipos_comprobantes }.should raise_error { |e|
|
268
268
|
e.should be_a Afipws::WSError
|
269
|
-
e.errors.should == [{ :
|
269
|
+
e.errors.should == [{ code: "600", msg: "No se corresponden token con firma" }, { code: "601", msg: "CUIT representada no incluida en token" }]
|
270
270
|
e.message.should == "600: No se corresponden token con firma; 601: CUIT representada no incluida en token"
|
271
271
|
}
|
272
272
|
end
|
@@ -274,11 +274,11 @@ describe Afipws::WSFE do
|
|
274
274
|
|
275
275
|
context "cálculo de fechas y períodos" do
|
276
276
|
it "periodo_para_consulta_caea" do
|
277
|
-
ws.periodo_para_consulta_caea(Date.new(2011,1,1)).should == { :
|
278
|
-
ws.periodo_para_consulta_caea(Date.new(2011,1,15)).should == { :
|
279
|
-
ws.periodo_para_consulta_caea(Date.new(2011,1,16)).should == { :
|
280
|
-
ws.periodo_para_consulta_caea(Date.new(2011,1,31)).should == { :
|
281
|
-
ws.periodo_para_consulta_caea(Date.new(2011,2,2)).should == { :
|
277
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,1)).should == { periodo: '201101', orden: 1 }
|
278
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,15)).should == { periodo: '201101', orden: 1 }
|
279
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,16)).should == { periodo: '201101', orden: 2 }
|
280
|
+
ws.periodo_para_consulta_caea(Date.new(2011,1,31)).should == { periodo: '201101', orden: 2 }
|
281
|
+
ws.periodo_para_consulta_caea(Date.new(2011,2,2)).should == { periodo: '201102', orden: 1 }
|
282
282
|
end
|
283
283
|
|
284
284
|
it "fecha_inicio_quincena_siguiente" do
|
@@ -293,7 +293,7 @@ describe Afipws::WSFE do
|
|
293
293
|
end
|
294
294
|
|
295
295
|
def fecha_inicio_quincena_siguiente fecha
|
296
|
-
Date.stubs(:
|
296
|
+
Date.stubs(today: fecha)
|
297
297
|
subject.fecha_inicio_quincena_siguiente
|
298
298
|
end
|
299
299
|
end
|
@@ -304,7 +304,7 @@ describe Afipws::WSFE do
|
|
304
304
|
end
|
305
305
|
|
306
306
|
it "no debería enviar tag tributos si el impTrib es 0" do
|
307
|
-
c2r(:
|
307
|
+
c2r(imp_trib: 0.0, tributos: { tributo: [] }).should_not have_key :tributos
|
308
308
|
end
|
309
309
|
end
|
310
310
|
end
|
data/spec/manual/test.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.expand_path('lib')); require 'afipws'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
ws = Afipws::WSFE.new :env => :development, :cuit => '20300032673', :cert => File.read('spec/manual/test.crt'), :key => File.read('spec/manual/test.key')
|
3
|
+
ws = Afipws::WSFE.new env: :development, cuit: '20300032673', cert: File.read('spec/manual/test.crt'), key: File.read('spec/manual/test.key'), savon: {log: true}
|
6
4
|
|
7
5
|
def obtener_ta ws
|
8
6
|
ws.cotizacion 'DOL'
|
@@ -16,26 +14,22 @@ def obtener_ta ws
|
|
16
14
|
end
|
17
15
|
|
18
16
|
def autorizar_comprobante ws
|
19
|
-
ultimo = ws.ultimo_comprobante_autorizado :
|
17
|
+
ultimo = ws.ultimo_comprobante_autorizado pto_vta: 1, cbte_tipo: 1
|
20
18
|
# cant_informar = ws.cant_max_registros_x_lote
|
21
19
|
cant_informar = 2
|
22
20
|
puts "Informando #{cant_informar} comprobantes"
|
23
21
|
comprobantes = (1..cant_informar).to_a.map do |i|
|
24
22
|
{
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
23
|
+
cbte_nro: ultimo + i, concepto: 1, doc_nro: 30521189203, doc_tipo: 80, cbte_fch: Date.today,
|
24
|
+
imp_total: 1270.48, imp_neto: 1049.98, imp_iva: 220.50, mon_id: 'PES', mon_cotiz: 1,
|
25
|
+
iva: { alic_iva: [{ id: 5, base_imp: 1049.98, importe: 220.50 }]}
|
28
26
|
}
|
29
27
|
end
|
30
|
-
puts ws.autorizar_comprobantes(:
|
28
|
+
puts ws.autorizar_comprobantes(cbte_tipo: 1, pto_vta: 1, comprobantes: comprobantes)
|
31
29
|
end
|
32
30
|
|
33
31
|
def consultar_caea ws
|
34
32
|
ws.consultar_caea Date.new(2011,2,3)
|
35
33
|
end
|
36
34
|
|
37
|
-
def soap_actions ws
|
38
|
-
ws.client.soap_actions
|
39
|
-
end
|
40
|
-
|
41
35
|
obtener_ta ws
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,24 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'afipws'
|
3
|
-
require '
|
3
|
+
require 'savon/mock/spec_helper'
|
4
|
+
require 'mocha'
|
5
|
+
require 'pry-byebug'
|
4
6
|
|
5
7
|
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
6
8
|
|
7
9
|
RSpec.configure do |config|
|
8
|
-
config.include Savon::
|
10
|
+
config.include Savon::SpecHelper
|
11
|
+
|
12
|
+
config.mock_with :mocha
|
13
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
14
|
+
config.alias_example_to :fit, focused: true
|
15
|
+
config.filter_run focused: true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
|
18
|
+
config.before(:all) { savon.mock! }
|
19
|
+
config.after(:all) { savon.unmock! }
|
9
20
|
end
|
10
21
|
|
11
|
-
|
22
|
+
def fixture file
|
23
|
+
File.read("#{Afipws::Root}/spec/fixtures/#{file}.xml")
|
24
|
+
end
|
data/spec/support/matchers.rb
CHANGED
@@ -1,37 +1,11 @@
|
|
1
|
-
RSpec::Matchers.define :match_xpath do |xpath,
|
1
|
+
RSpec::Matchers.define :match_xpath do |xpath, expected_value|
|
2
2
|
match do |xml|
|
3
|
-
xml = Nokogiri::XML xml
|
4
|
-
xml.
|
3
|
+
@xml = Nokogiri::XML xml
|
4
|
+
@xml.remove_namespaces!
|
5
|
+
@xml.xpath(xpath).text.should == expected_value.to_s
|
5
6
|
end
|
6
|
-
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
module Mocha
|
11
|
-
module ParameterMatchers
|
12
|
-
def has_path(paths)
|
13
|
-
HasPath.new(paths)
|
14
|
-
end
|
15
|
-
|
16
|
-
class HasPath < Base # :nodoc:
|
17
|
-
def initialize(paths)
|
18
|
-
@paths = paths
|
19
|
-
end
|
20
|
-
|
21
|
-
def matches?(available_parameters)
|
22
|
-
parameter = available_parameters.shift
|
23
|
-
return false unless parameter.is_a? Hash
|
24
|
-
@paths.all? do |path|
|
25
|
-
path, expected_value = path
|
26
|
-
actual_value = parameter.fetch_path path.gsub('/', '/wsdl:')
|
27
|
-
@failed_path, @failed_value, @actual_value = path, expected_value, actual_value
|
28
|
-
expected_value == actual_value
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def mocha_inspect
|
33
|
-
"has_path(#{@failed_path.mocha_inspect} => #{@failed_value.mocha_inspect} | Actual: #{@actual_value.mocha_inspect})"
|
34
|
-
end
|
35
|
-
end
|
8
|
+
failure_message_for_should do |actual|
|
9
|
+
"expected xpath '#{xpath}' with value '#{expected_value}' in doc:\n#{@xml}"
|
36
10
|
end
|
37
11
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Savon 2 sólo permite verificar los params del mensaje como un hash lo cual es poco flexible. Con esto permito pasarle xpaths.
|
2
|
+
|
3
|
+
module Savon
|
4
|
+
module MessageMatcher
|
5
|
+
def actual(operation_name, builder, globals, locals)
|
6
|
+
super.update request: builder.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def verify_message!
|
10
|
+
if @expected[:message].respond_to? :verify!
|
11
|
+
@expected[:message].verify! @actual[:request]
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
MockExpectation.prepend MessageMatcher
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_path(paths)
|
22
|
+
HasXPath.new(paths)
|
23
|
+
end
|
24
|
+
|
25
|
+
class HasXPath
|
26
|
+
include RSpec::Matchers
|
27
|
+
|
28
|
+
def initialize(paths)
|
29
|
+
@paths = paths
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify! xml
|
33
|
+
@actual_xml = xml
|
34
|
+
@paths.each do |(path, value)|
|
35
|
+
@expected_xpath, @expected_value = path, value
|
36
|
+
@actual_xml.should match_xpath @expected_xpath, @expected_value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: afipws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emmanuel Nicolau
|
@@ -14,52 +14,66 @@ dependencies:
|
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.14.1
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.14.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 10.4.2
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 10.4.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: mocha
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.9.10
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.9.10
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: guard-rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.3.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.3.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '0'
|
62
|
-
type: :
|
76
|
+
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
@@ -67,7 +81,7 @@ dependencies:
|
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: builder
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
@@ -81,21 +95,21 @@ dependencies:
|
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: savon
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - "
|
101
|
+
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
103
|
+
version: 2.11.0
|
90
104
|
type: :runtime
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- - "
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
110
|
+
version: 2.11.0
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: nokogiri
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,7 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: activesupport
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: i18n
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
@@ -137,19 +151,19 @@ dependencies:
|
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
154
|
+
name: httpclient
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - ">="
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
159
|
+
version: '0'
|
146
160
|
type: :runtime
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - ">="
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
166
|
+
version: '0'
|
153
167
|
description: ''
|
154
168
|
email:
|
155
169
|
- emmanicolau@gmail.com
|
@@ -216,6 +230,7 @@ files:
|
|
216
230
|
- spec/manual/test.rb
|
217
231
|
- spec/spec_helper.rb
|
218
232
|
- spec/support/matchers.rb
|
233
|
+
- spec/support/savon_extensions.rb
|
219
234
|
homepage: ''
|
220
235
|
licenses: []
|
221
236
|
metadata: {}
|
@@ -279,3 +294,4 @@ test_files:
|
|
279
294
|
- spec/manual/test.rb
|
280
295
|
- spec/spec_helper.rb
|
281
296
|
- spec/support/matchers.rb
|
297
|
+
- spec/support/savon_extensions.rb
|