bravo 1.0.0.alpha → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -3
- data/.travis.yml +1 -2
- data/CHANGELOG +5 -2
- data/Gemfile +1 -1
- data/README.md +78 -19
- data/bin/bravo +10 -10
- data/bravo.gemspec +9 -4
- data/lib/bravo.rb +56 -16
- data/lib/bravo/auth_data.rb +3 -3
- data/lib/bravo/bill.rb +41 -41
- data/lib/bravo/constants.rb +48 -48
- data/lib/bravo/core_ext/string.rb +1 -1
- data/lib/bravo/reference.rb +6 -5
- data/lib/bravo/version.rb +2 -2
- data/lib/bravo/wsaa.rb +8 -8
- data/spec/bravo/auth_data_spec.rb +3 -3
- data/spec/bravo/bill_spec.rb +37 -36
- data/spec/bravo/wsaa_spec.rb +16 -20
- data/spec/fixtures/certs/cert.crt +22 -0
- data/spec/fixtures/certs/pkey +15 -0
- data/spec/spec_helper.rb +17 -9
- metadata +58 -6
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
*Bravo 1.0.0.
|
1
|
+
*Bravo 1.0.0.rc1 (November 25, 2013)*
|
2
|
+
* Added full support for Savon logging options
|
3
|
+
|
4
|
+
*Bravo 1.0.0.alpha (March 30 - Nov 25, 2013)*
|
2
5
|
|
3
6
|
* Updated dependencies
|
4
7
|
* Added reference class that will pass any method to the api, without a message
|
@@ -24,4 +27,4 @@
|
|
24
27
|
|
25
28
|
*Bravo 0.2.0 (March 04, 2011)*
|
26
29
|
|
27
|
-
* Bill#response returns a complete hash from WSFE response [leanucci]
|
30
|
+
* Bill#response returns a complete hash from WSFE response [leanucci]
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,47 +1,106 @@
|
|
1
1
|
# Bravo ![Travis status](https://travis-ci.org/leanucci/bravo.png)
|
2
2
|
|
3
|
-
> la gema de facturación electrónica argentina
|
4
|
-
|
5
3
|
[~~Bravo~~](http://images.coveralia.com/audio/b/Bravo-Desierto_Sin_Amor-Frontal.jpg) Bravo permite la obtención del [~~C.A.E~~](http://www.muevamueva.com/masmusica/latina/cae/images/fotos.5.gif) C.A.E. (Código de Autorización Electrónico) por medio del Web Service de Facturación Electrónica provisto por AFIP.
|
6
4
|
|
7
|
-
##
|
5
|
+
## Requisitos
|
6
|
+
|
7
|
+
Para poder autorizar comprobantes mediante el WSFE, AFIP requiere de ciertos pasos detallados a continuación:
|
8
|
+
|
9
|
+
* Generar una clave privada para la aplicación.
|
10
|
+
* Generar un CSR (Certificate Signing Request) utilizando el número de CUIT que emitirá los comprobantes y la clave privada del paso anterior. Se deberá enviar a AFIP el CSR para obtener el Certificado X.509 que se utilizará en el proceso de autorización de comprobantes.
|
11
|
+
* Para el entorno de Testing, se debe enviar el X.509 por email a _webservices@afip.gov.ar_.
|
12
|
+
* Para el entorno de Producción, el trámite se hace a través del portal [AFIP](http://www.afip.gov.ar)
|
13
|
+
* El certificado X.509 y la clave privada son utilizados por Bravo para obtener el token y signature a incluir en el header de autenticacion en cada request que hagamaos a los servicios de AFIP.
|
14
|
+
|
15
|
+
|
16
|
+
### OpenSSL
|
8
17
|
|
9
|
-
|
18
|
+
Para cumplir con los requisitos de encriptación del [Web Service de Autenticación y Autorización](http://www.afip.gov.ar/ws/WSAA/README.txt) (WSAA), Bravo requiere [OpenSSL](http://openssl.org) en cualquier versión posterior a la 1.0.0a.
|
10
19
|
|
11
|
-
|
20
|
+
Como regla general, basta correr desde la línea de comandos ```openssl cms```
|
12
21
|
|
13
|
-
|
22
|
+
Si el comando ```cms``` no está disponible, se debe actualizar OpenSSL.
|
14
23
|
|
24
|
+
### Certificados
|
15
25
|
|
16
|
-
|
26
|
+
AFIP exige para acceder a sus Web Services, la utilización del WSAA. Este servicio se encarga de la autorización y autenticación de cada request hecho al web service.
|
17
27
|
|
28
|
+
Una vez instalada la version correcta de OpenSSL, podemos generar la clave privada y el CSR.
|
18
29
|
|
19
|
-
|
30
|
+
* [Documentación WSAA](http://www.afip.gov.ar/ws/WSAA/Especificacion_Tecnica_WSAA_1.2.0.pdf)
|
31
|
+
* [Cómo generar el CSR](https://gist.github.com/leanucci/7520622)
|
20
32
|
|
21
|
-
Para esto hace falta generar el CSR (Certificate Signature Request).
|
22
33
|
|
23
34
|
## Uso
|
24
35
|
|
25
|
-
|
36
|
+
Luego de haber obtenido el certificado X.509, podemos comenzar a utilizar Bravo en el entorno para el cual sirve el certificado.
|
26
37
|
|
27
|
-
|
38
|
+
### Configuración
|
28
39
|
|
29
|
-
|
30
|
-
Bravo.pkey = path_al_pkey
|
31
|
-
Bravo.cert = path_al_cert
|
32
|
-
Bravo.cuit = 20881234569
|
40
|
+
Bravo no asume valores por defecto, por lo cual hay que configurar de forma explícita todos los parámetros:
|
33
41
|
|
42
|
+
* ```pkey``` ruta a la clave privada
|
43
|
+
* ```cert``` ruta al certificado X.509
|
44
|
+
* ```cuit``` el número de CUIT para el que queremos emitir los comprobantes
|
45
|
+
* ```sale_point``` el punto de venta a utilizar (ante la duda consulte a su contador)
|
46
|
+
* ```default_concepto, default_documento y default_moneda``` estos valores pueden configurarse para no tener que pasarlos cada vez que emitamos un comprobante, ya que no suelen cambiar entre comprobantes emitidos por el mismo vendedor.
|
47
|
+
* ```own_iva_cond``` condicion propia ante el IVA
|
48
|
+
* ```openssl_bin``` path al ejecutable de OpenSSL
|
34
49
|
|
35
|
-
Bravo acepta más opciones, para más detalles ver el archivo [spec/spec_helper.rb](https://github.com/vurbia/Bravo/blob/master/spec/spec_helper.rb)
|
36
50
|
|
37
|
-
|
51
|
+
Ejemplo de configuración tomado del spec_helper de Bravo:
|
52
|
+
|
53
|
+
|
54
|
+
require 'bravo'
|
55
|
+
|
56
|
+
Bravo.pkey = 'spec/fixtures/certs/pkey'
|
57
|
+
Bravo.cert = 'spec/fixtures/certs/cert.crt'
|
58
|
+
Bravo.cuit = '20287740027'
|
59
|
+
Bravo.sale_point = '0002'
|
60
|
+
Bravo.default_concepto = 'Productos y Servicios'
|
61
|
+
Bravo.default_documento = 'CUIT'
|
62
|
+
Bravo.default_moneda = :peso
|
63
|
+
Bravo.own_iva_cond = :responsable_inscripto
|
64
|
+
Bravo.verbose = 'true'
|
65
|
+
Bravo.openssl_bin = '/usr/local/Cellar/openssl/1.0.1e/bin/openssl'
|
66
|
+
Bravo::AuthData.environment = :test
|
67
|
+
|
68
|
+
### Emisión de comprobantes
|
69
|
+
|
70
|
+
Para emitir un comprobante, basta con:
|
71
|
+
|
72
|
+
* instanciar la clase `Bill`,
|
73
|
+
* pasarle los parámetros típicos del comprobante, como si lo llenásemos a mano,
|
74
|
+
* llamar el método `authorize`, para que el WSFE autorice el comprobante que acabamos de 'llenar':
|
75
|
+
|
76
|
+
#### Ejemplo
|
77
|
+
|
78
|
+
Luego de configurar Bravo, autorizamos una factura:
|
79
|
+
|
80
|
+
* Comprobante: Factura
|
81
|
+
* Tipo: 'B'
|
82
|
+
* A: consumidor final
|
83
|
+
* Total: $ 100 (si fuera una factura tipo A, este valor es el neto, y Bravo calcula el IVA correspondiente)
|
84
|
+
|
85
|
+
|
86
|
+
Código de ejemplo para la configuración anterior:
|
87
|
+
|
88
|
+
|
89
|
+
factura = Bravo::Bill.new
|
90
|
+
|
91
|
+
factura.net = 100.00 # el neto de la factura, total para Consumidor final
|
92
|
+
factura.aliciva_id = 2 # define la alicuota de iva a utilizar, ver archivo constants.
|
93
|
+
factura.iva_cond = :consumidor_final # la condición ante el iva del comprador
|
94
|
+
factura.concepto = 'Servicios' # concepto de la factura
|
95
|
+
factura.invoice_type = :invoice # el tipo de comprobante a emitir, en este caso factura.
|
38
96
|
|
39
|
-
|
97
|
+
bill.authorize
|
40
98
|
|
99
|
+
bill.response.cae # contiene el cae para este comprobante.
|
41
100
|
|
42
101
|
## TODO list
|
43
102
|
|
44
|
-
* rdoc
|
103
|
+
* ~~rdoc~~
|
45
104
|
* mensajes de error más completos
|
46
105
|
|
47
106
|
|
data/bin/bravo
CHANGED
@@ -8,13 +8,13 @@ module Bravo
|
|
8
8
|
#
|
9
9
|
class Bravo < Thor
|
10
10
|
|
11
|
-
desc
|
12
|
-
method_option :bin, type: :string, required: true, desc:
|
13
|
-
method_option :pkey, type: :string, desc:
|
14
|
-
method_option :sn, type: :string, required: true, desc:
|
15
|
-
method_option :cn, type: :string, required: true, desc:
|
16
|
-
method_option :cuit, type: :numeric, required: true, desc:
|
17
|
-
method_option :out, type: :string, default:
|
11
|
+
desc 'gencsr', 'Crea el Certificate Signature Request'
|
12
|
+
method_option :bin, type: :string, required: true, desc: 'El path completo al binario de openssl'
|
13
|
+
method_option :pkey, type: :string, desc: 'Path a una clave privada preexistente. Si se omite, se crea una clave en --out'
|
14
|
+
method_option :sn, type: :string, required: true, desc: 'Nombre del servidor. Sin uso práctico, es requerido por AFIP'
|
15
|
+
method_option :cn, type: :string, required: true, desc: 'Nombre de la compañía. Sin uso práctico, es requerido por AFIP'
|
16
|
+
method_option :cuit, type: :numeric, required: true, desc: 'Número de CUIT sin guiones. Ejemplo: 20876543217'
|
17
|
+
method_option :out, type: :string, default: 'bravo-certs', desc: 'Directorio de destino para los archivos creados. Si se omite, se crea el directorio bravo-certs en pwd'
|
18
18
|
|
19
19
|
# Certificate Signature Request wrapper for bravo.
|
20
20
|
#
|
@@ -41,16 +41,16 @@ module Bravo
|
|
41
41
|
-subj "/C=AR/O=#{ sn }/CN=#{ cn }/serialNumber=CUIT #{ cuit }"\
|
42
42
|
-out #{ out_path }pedido-#{ cuit }`
|
43
43
|
|
44
|
-
say(
|
44
|
+
say('Hecho!', :green)
|
45
45
|
end
|
46
46
|
|
47
47
|
protected
|
48
48
|
# Creates a new private key
|
49
49
|
#
|
50
50
|
def create_pkey(bin,out_path)
|
51
|
-
say(
|
51
|
+
say('Creando pkey', :cyan)
|
52
52
|
`#{ bin } genrsa -out #{ out_path }pkey 1024`
|
53
|
-
say(
|
53
|
+
say('Hecho!\n\n', :green)
|
54
54
|
"#{ out_path }pkey"
|
55
55
|
end
|
56
56
|
end
|
data/bravo.gemspec
CHANGED
@@ -10,17 +10,22 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.email = ["leanucci@gmail.com"]
|
11
11
|
gem.description = %q{Adaptador para el Web Service de Facturacion Electrónica de AFIP}
|
12
12
|
gem.summary = %q{Adaptador WSFE}
|
13
|
-
gem.homepage = "
|
13
|
+
gem.homepage = "https://github.com/leanucci/bravo#readme"
|
14
14
|
gem.date = %q(2011-03-14)
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.files.reject! { |f| f.include? 'vcr' }
|
17
18
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
20
|
gem.require_paths = ["lib", "bin"]
|
20
21
|
|
21
|
-
gem.add_runtime_dependency(%q<savon>, ["~> 2.
|
22
|
-
gem.add_runtime_dependency(%q<thor>, ["~> 0.
|
22
|
+
gem.add_runtime_dependency(%q<savon>, ["~> 2.3.0"])
|
23
|
+
gem.add_runtime_dependency(%q<thor>, ["~> 0.17.0"])
|
24
|
+
|
23
25
|
gem.add_development_dependency(%q<rspec>, ["~> 2.12.0"])
|
24
26
|
gem.add_development_dependency(%q<rspec-mocks>, ["~> 2.12.1"])
|
25
27
|
gem.add_development_dependency(%q<rake>, ["~> 10.0.3"])
|
26
|
-
|
28
|
+
gem.add_development_dependency(%q<vcr>, ["~> 2.4.0"])
|
29
|
+
gem.add_development_dependency(%q<simplecov>, ["~> 0.7.1"])
|
30
|
+
gem.add_development_dependency(%q<fakeweb>, ["~> 1.3.0"])
|
31
|
+
end
|
data/lib/bravo.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bravo/version'
|
3
|
+
require 'bravo/constants'
|
4
|
+
require 'savon'
|
5
|
+
require 'bravo/core_ext/float'
|
6
|
+
require 'bravo/core_ext/hash'
|
7
|
+
require 'bravo/core_ext/string'
|
8
8
|
|
9
9
|
module Bravo
|
10
10
|
|
@@ -12,21 +12,61 @@ module Bravo
|
|
12
12
|
#
|
13
13
|
class NullOrInvalidAttribute < StandardError; end
|
14
14
|
|
15
|
-
# Exception
|
15
|
+
# Exception Class for missing or invalid certifficate
|
16
16
|
#
|
17
17
|
class MissingCertificate < StandardError; end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
|
20
|
+
# This class handles the logging options
|
21
|
+
#
|
22
|
+
class Logger < Struct.new(:log, :pretty_xml, :level)
|
23
|
+
# @param log [Boolean] wether to log or not.
|
24
|
+
# @param pretty_xml [Boolean] pass true to format xml in a readable way.
|
25
|
+
# @param level [Symbol] one of `:debug`, `:info`, `:warn`, `:error`, `:fatal`.
|
26
|
+
|
27
|
+
def initialize(log = false, level = :debug, pretty_xml = true)
|
28
|
+
self.log = log
|
29
|
+
self.pretty_xml = pretty_xml
|
30
|
+
self.level = level
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Hash] returns a hash with the proper logging optios for Savon.
|
34
|
+
def logger_options
|
35
|
+
{ log: self.log, pretty_print_xml: self.pretty_xml, log_level: self.level }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
autoload :Authorizer, 'bravo/authorizer'
|
40
|
+
autoload :AuthData, 'bravo/auth_data'
|
41
|
+
autoload :Bill, 'bravo/bill'
|
42
|
+
autoload :Constants, 'bravo/constants'
|
43
|
+
autoload :Wsaa, 'bravo/wsaa'
|
44
|
+
autoload :Reference, 'bravo/reference'
|
25
45
|
|
26
46
|
extend self
|
27
47
|
|
28
48
|
attr_accessor :cuit, :sale_point, :default_documento, :pkey, :cert,
|
29
49
|
:default_concepto, :default_moneda, :own_iva_cond,
|
30
|
-
:
|
50
|
+
:openssl_bin
|
51
|
+
|
52
|
+
class << self
|
53
|
+
# Receiver of the logging configuration options.
|
54
|
+
# @param opts [Hash] pass a hash with `log`, `pretty_xml` and `level` keys to set
|
55
|
+
# them.
|
56
|
+
def logger=(opts)
|
57
|
+
@logger ||= Logger.new(opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Sets the logger options to the default values or returns the previously set
|
61
|
+
# logger options
|
62
|
+
# @return [Logger]
|
63
|
+
def logger
|
64
|
+
@logger ||= Logger.new
|
65
|
+
end
|
31
66
|
|
32
|
-
|
67
|
+
# Returs the formatted logger options to be used by Savon.
|
68
|
+
def logger_options
|
69
|
+
logger.logger_options
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/bravo/auth_data.rb
CHANGED
@@ -34,14 +34,14 @@ module Bravo
|
|
34
34
|
# @return [Hash]
|
35
35
|
#
|
36
36
|
def auth_hash
|
37
|
-
{
|
37
|
+
{ 'Token' => Bravo::TOKEN, 'Sign' => Bravo::SIGN, 'Cuit' => Bravo.cuit }
|
38
38
|
end
|
39
39
|
|
40
40
|
# Returns the right wsaa url for the specific environment
|
41
41
|
# @return [String]
|
42
42
|
#
|
43
43
|
def wsaa_url
|
44
|
-
raise
|
44
|
+
raise 'Environment not sent to either :test or :production' unless Bravo::URLS.keys.include? environment
|
45
45
|
Bravo::URLS[environment][:wsaa]
|
46
46
|
end
|
47
47
|
|
@@ -49,7 +49,7 @@ module Bravo
|
|
49
49
|
# @return [String]
|
50
50
|
#
|
51
51
|
def wsfe_url
|
52
|
-
raise
|
52
|
+
raise 'Environment not sent to either :test or :production' unless Bravo::URLS.keys.include? environment
|
53
53
|
Bravo::URLS[environment][:wsfe]
|
54
54
|
end
|
55
55
|
|
data/lib/bravo/bill.rb
CHANGED
@@ -14,8 +14,9 @@ module Bravo
|
|
14
14
|
|
15
15
|
def initialize(attrs = {})
|
16
16
|
Bravo::AuthData.fetch
|
17
|
-
|
18
|
-
@
|
17
|
+
opts = { wsdl: Bravo::AuthData.wsfe_url}.merge! Bravo.logger_options
|
18
|
+
@client = Savon.client(opts)
|
19
|
+
@body = { 'Auth' => Bravo::AuthData.auth_hash }
|
19
20
|
self.iva_cond = attrs[:iva_cond]
|
20
21
|
@net = attrs[:net] || 0
|
21
22
|
self.documento = attrs[:documento] || Bravo.default_documento
|
@@ -29,10 +30,9 @@ module Bravo
|
|
29
30
|
# @return [String] the document type string
|
30
31
|
#
|
31
32
|
def cbte_type
|
32
|
-
own_iva = Bravo::BILL_TYPE.has_key?(Bravo.own_iva_cond) ? Bravo::BILL_TYPE[Bravo.own_iva_cond] : raise(NullOrInvalidAttribute.new,
|
33
|
-
target_iva = own_iva.has_key?(iva_cond) ? own_iva[iva_cond] : raise(NullOrInvalidAttribute.new,
|
34
|
-
type = target_iva.has_key?(invoice_type) ? target_iva[invoice_type] : raise(NullOrInvalidAttribute.new,
|
35
|
-
|
33
|
+
own_iva = Bravo::BILL_TYPE.has_key?(Bravo.own_iva_cond) ? Bravo::BILL_TYPE[Bravo.own_iva_cond] : raise(NullOrInvalidAttribute.new, 'Own iva_cond is invalid.')
|
34
|
+
target_iva = own_iva.has_key?(iva_cond) ? own_iva[iva_cond] : raise(NullOrInvalidAttribute.new, 'Target iva_cond is invalid.')
|
35
|
+
type = target_iva.has_key?(invoice_type) ? target_iva[invoice_type] : raise(NullOrInvalidAttribute.new, 'Selected invoice_type is invalid.')
|
36
36
|
end
|
37
37
|
|
38
38
|
# Calculates the total field for the invoice by adding
|
@@ -60,7 +60,7 @@ module Bravo
|
|
60
60
|
def authorize
|
61
61
|
setup_bill
|
62
62
|
response = client.call(:fecae_solicitar) do |soap|
|
63
|
-
# soap.namespaces[
|
63
|
+
# soap.namespaces['xmlns'] = 'http://ar.gov.afip.dif.FEV1/'
|
64
64
|
soap.message body
|
65
65
|
end
|
66
66
|
|
@@ -74,36 +74,36 @@ module Bravo
|
|
74
74
|
def setup_bill
|
75
75
|
today = Time.new.strftime('%Y%m%d')
|
76
76
|
|
77
|
-
fecaereq = {
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
detail = fecaereq[
|
96
|
-
|
97
|
-
detail[
|
98
|
-
detail[
|
99
|
-
detail[
|
100
|
-
detail[
|
101
|
-
detail[
|
77
|
+
fecaereq = { 'FeCAEReq' => {
|
78
|
+
'FeCabReq' => Bravo::Bill.header(cbte_type),
|
79
|
+
'FeDetReq' => {
|
80
|
+
'FECAEDetRequest' => {
|
81
|
+
'Concepto' => Bravo::CONCEPTOS[concepto],
|
82
|
+
'DocTipo' => Bravo::DOCUMENTOS[documento],
|
83
|
+
'CbteFch' => today,
|
84
|
+
'ImpTotConc' => 0.00,
|
85
|
+
'MonId' => Bravo::MONEDAS[moneda][:codigo],
|
86
|
+
'MonCotiz' => 1,
|
87
|
+
'ImpOpEx' => 0.00,
|
88
|
+
'ImpTrib' => 0.00,
|
89
|
+
'Iva' => {
|
90
|
+
'AlicIva' => {
|
91
|
+
'Id' => '5',
|
92
|
+
'BaseImp' => net,
|
93
|
+
'Importe' => iva_sum } } } } } }
|
94
|
+
|
95
|
+
detail = fecaereq['FeCAEReq']['FeDetReq']['FECAEDetRequest']
|
96
|
+
|
97
|
+
detail['DocNro'] = doc_num
|
98
|
+
detail['ImpNeto'] = net.to_f
|
99
|
+
detail['ImpIVA'] = iva_sum
|
100
|
+
detail['ImpTotal'] = total
|
101
|
+
detail['CbteDesde'] = detail['CbteHasta'] = Bravo::Reference.next_bill_number(cbte_type)
|
102
102
|
|
103
103
|
unless concepto == 0
|
104
|
-
detail.merge!({
|
105
|
-
|
106
|
-
|
104
|
+
detail.merge!({ 'FchServDesde' => fch_serv_desde || today,
|
105
|
+
'FchServHasta' => fch_serv_hasta || today,
|
106
|
+
'FchVtoPago' => due_date || today })
|
107
107
|
end
|
108
108
|
|
109
109
|
body.merge!(fecaereq)
|
@@ -113,7 +113,7 @@ module Bravo
|
|
113
113
|
# @return [Boolean] the response result
|
114
114
|
#
|
115
115
|
def authorized?
|
116
|
-
!response.nil? && response.header_result ==
|
116
|
+
!response.nil? && response.header_result == 'A' && response.detail_result == 'A'
|
117
117
|
end
|
118
118
|
|
119
119
|
private
|
@@ -124,7 +124,7 @@ module Bravo
|
|
124
124
|
#
|
125
125
|
def header(cbte_type)
|
126
126
|
# todo sacado de la factura
|
127
|
-
{
|
127
|
+
{ 'CantReg' => '1', 'CbteTipo' => cbte_type, 'PtoVta' => Bravo.sale_point }
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
@@ -139,10 +139,10 @@ module Bravo
|
|
139
139
|
response_header = result[:fe_cab_resp]
|
140
140
|
response_detail = result[:fe_det_resp][:fecae_det_response]
|
141
141
|
|
142
|
-
request_header = body[
|
143
|
-
request_detail = body[
|
142
|
+
request_header = body['FeCAEReq']['FeCabReq'].underscore_keys.symbolize_keys
|
143
|
+
request_detail = body['FeCAEReq']['FeDetReq']['FECAEDetRequest'].underscore_keys.symbolize_keys
|
144
144
|
|
145
|
-
iva = request_detail.delete(:iva)[
|
145
|
+
iva = request_detail.delete(:iva)['AlicIva'].underscore_keys.symbolize_keys
|
146
146
|
|
147
147
|
request_detail.merge!(iva)
|
148
148
|
|
@@ -160,7 +160,7 @@ module Bravo
|
|
160
160
|
}.merge!(request_header).merge!(request_detail)
|
161
161
|
|
162
162
|
keys, values = response_hash.to_a.transpose
|
163
|
-
self.response = (defined?(Struct::Response) ? Struct::Response : Struct.new(
|
163
|
+
self.response = (defined?(Struct::Response) ? Struct::Response : Struct.new('Response', *keys)).new(*values)
|
164
164
|
end
|
165
165
|
end
|
166
166
|
end
|
data/lib/bravo/constants.rb
CHANGED
@@ -5,81 +5,81 @@ module Bravo
|
|
5
5
|
# This constant contains the invoice types mappings between codes and names
|
6
6
|
# used by WSFE.
|
7
7
|
CBTE_TIPO = {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
8
|
+
'01'=>'Factura A',
|
9
|
+
'02'=>'Nota de Débito A',
|
10
|
+
'03'=>'Nota de Crédito A',
|
11
|
+
'04'=>'Recibos A',
|
12
|
+
'05'=>'Notas de Venta al contado A',
|
13
|
+
'06'=>'Factura B',
|
14
|
+
'07'=>'Nota de Debito B',
|
15
|
+
'08'=>'Nota de Credito B',
|
16
|
+
'09'=>'Recibos B',
|
17
|
+
'10'=>'Notas de Venta al contado B',
|
18
|
+
'34'=>'Cbtes. A del Anexo I, Apartado A,inc.f),R.G.Nro. 1415',
|
19
|
+
'35'=>'Cbtes. B del Anexo I,Apartado A,inc. f),R.G. Nro. 1415',
|
20
|
+
'39'=>'Otros comprobantes A que cumplan con R.G.Nro. 1415',
|
21
|
+
'40'=>'Otros comprobantes B que cumplan con R.G.Nro. 1415',
|
22
|
+
'60'=>'Cta de Vta y Liquido prod. A',
|
23
|
+
'61'=>'Cta de Vta y Liquido prod. B',
|
24
|
+
'63'=>'Liquidacion A',
|
25
|
+
'64'=>'Liquidacion B'
|
26
26
|
}
|
27
27
|
|
28
28
|
# Name to code mapping for Sale types.
|
29
29
|
#
|
30
|
-
CONCEPTOS = {
|
30
|
+
CONCEPTOS = { 'Productos'=>'01', 'Servicios'=>'02', 'Productos y Servicios'=>'03' }
|
31
31
|
|
32
32
|
# Name to code mapping for types of documents.
|
33
33
|
#
|
34
34
|
DOCUMENTOS = {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
'CUIT'=>'80',
|
36
|
+
'CUIL'=>'86',
|
37
|
+
'CDI'=>'87',
|
38
|
+
'LE'=>'89',
|
39
|
+
'LC'=>'90',
|
40
|
+
'CI Extranjera'=>'91',
|
41
|
+
'en tramite'=>'92',
|
42
|
+
'Acta Nacimiento'=>'93',
|
43
|
+
'CI Bs. As. RNP'=>'95',
|
44
|
+
'DNI'=>'96',
|
45
|
+
'Pasaporte'=>'94',
|
46
|
+
'Doc. (Otro)'=>'99' }
|
47
47
|
|
48
48
|
# Currency code and names hash identified by a symbol
|
49
49
|
#
|
50
50
|
MONEDAS = {
|
51
|
-
:peso => { :codigo =>
|
52
|
-
:dolar => { :codigo =>
|
53
|
-
:real => { :codigo =>
|
54
|
-
:euro => { :codigo =>
|
55
|
-
:oro => { :codigo =>
|
51
|
+
:peso => { :codigo => 'PES', :nombre =>'Pesos Argentinos' },
|
52
|
+
:dolar => { :codigo => 'DOL', :nombre =>'Dolar Estadounidense' },
|
53
|
+
:real => { :codigo => '012', :nombre =>'Real' },
|
54
|
+
:euro => { :codigo => '060', :nombre =>'Euro' },
|
55
|
+
:oro => { :codigo => '049', :nombre =>'Gramos de Oro Fino' } }
|
56
56
|
|
57
57
|
|
58
58
|
# Tax percentage and codes according to each iva combination
|
59
59
|
#
|
60
|
-
ALIC_IVA = [[
|
60
|
+
ALIC_IVA = [['03', 0], ['04', 0.105], ['05', 0.21], ['06', 0.27]]
|
61
61
|
|
62
62
|
|
63
63
|
|
64
64
|
# This hash keeps the codes for A document types by operation
|
65
65
|
#
|
66
66
|
BILL_TYPE_A = {
|
67
|
-
:invoice =>
|
68
|
-
:debit =>
|
69
|
-
:credit =>
|
67
|
+
:invoice => '01',
|
68
|
+
:debit => '02',
|
69
|
+
:credit => '03' }
|
70
70
|
|
71
71
|
# This hash keeps the codes for A document types by operation
|
72
72
|
#
|
73
73
|
BILL_TYPE_B = {
|
74
|
-
:invoice =>
|
75
|
-
:debit =>
|
76
|
-
:credit =>
|
74
|
+
:invoice => '06',
|
75
|
+
:debit => '07',
|
76
|
+
:credit => '08' }
|
77
77
|
|
78
78
|
# This hash keeps the different buyer and invoice type mapping corresponding to
|
79
79
|
# the seller's iva condition and invoice kind.
|
80
80
|
# Usage:
|
81
81
|
# `BILL_TYPE[seller_iva_cond][buyer_iva_cond][invoice_type]` #=> invoice type as string
|
82
|
-
# `BILL_TYPE[:responsable_inscripto][:responsable_inscripto][:invoice]` #=>
|
82
|
+
# `BILL_TYPE[:responsable_inscripto][:responsable_inscripto][:invoice]` #=> '01'
|
83
83
|
#
|
84
84
|
BILL_TYPE = {
|
85
85
|
:responsable_inscripto => {
|
@@ -91,9 +91,9 @@ module Bravo
|
|
91
91
|
# This hash keeps the set of urls for wsaa and wsfe for production and testing envs
|
92
92
|
#
|
93
93
|
URLS = {
|
94
|
-
:test => { :wsaa =>
|
95
|
-
:wsfe =>
|
94
|
+
:test => { :wsaa => 'https://wsaahomo.afip.gov.ar/ws/services/LoginCms',
|
95
|
+
:wsfe => 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL' },
|
96
96
|
|
97
|
-
:production => { :wsaa =>
|
98
|
-
:wsfe =>
|
97
|
+
:production => { :wsaa => 'https://wsaa.afip.gov.ar/ws/services/LoginCms',
|
98
|
+
:wsfe => 'https://servicios1.afip.gov.ar/wsfev1/service.asmx' } }
|
99
99
|
end
|
data/lib/bravo/reference.rb
CHANGED
@@ -8,8 +8,8 @@ module Bravo
|
|
8
8
|
def self.next_bill_number(cbte_type)
|
9
9
|
set_client
|
10
10
|
resp = @client.call(:fe_comp_ultimo_autorizado) do |soap|
|
11
|
-
# soap.namespaces[
|
12
|
-
soap.message
|
11
|
+
# soap.namespaces['xmlns'] = 'http://ar.gov.afip.dif.FEV1/'
|
12
|
+
soap.message 'Auth' => Bravo::AuthData.auth_hash, 'PtoVta' => Bravo.sale_point, 'CbteTipo' => cbte_type
|
13
13
|
end
|
14
14
|
|
15
15
|
resp.to_hash[:fe_comp_ultimo_autorizado_response][:fe_comp_ultimo_autorizado_result][:cbte_nro].to_i + 1
|
@@ -21,7 +21,7 @@ module Bravo
|
|
21
21
|
def self.get_custom(operation)
|
22
22
|
set_client
|
23
23
|
resp = @client.call(operation) do |soap|
|
24
|
-
soap.message
|
24
|
+
soap.message 'Auth' => Bravo::AuthData.auth_hash
|
25
25
|
end
|
26
26
|
resp.to_hash
|
27
27
|
end
|
@@ -31,7 +31,8 @@ module Bravo
|
|
31
31
|
#
|
32
32
|
def self.set_client
|
33
33
|
Bravo::AuthData.fetch
|
34
|
-
|
34
|
+
opts = { wsdl: Bravo::AuthData.wsfe_url }.merge! Bravo.logger_options
|
35
|
+
@client = Savon.client(opts)
|
35
36
|
end
|
36
37
|
end
|
37
|
-
end
|
38
|
+
end
|
data/lib/bravo/version.rb
CHANGED
data/lib/bravo/wsaa.rb
CHANGED
@@ -17,21 +17,21 @@ module Bravo
|
|
17
17
|
end
|
18
18
|
|
19
19
|
protected
|
20
|
-
# Builds the xml for the
|
20
|
+
# Builds the xml for the 'Ticket de Requerimiento de Acceso'
|
21
21
|
# @return [String] containing the request body
|
22
22
|
#
|
23
23
|
def self.build_tra
|
24
|
-
now = Time.now
|
25
|
-
from = now.strftime(
|
26
|
-
to = (
|
27
|
-
id = now.strftime(
|
24
|
+
@now = (Time.now) - 120
|
25
|
+
@from = @now.strftime('%FT%T%:z')
|
26
|
+
@to = (@now + ((12*60*60))).strftime('%FT%T%:z')
|
27
|
+
@id = @now.strftime('%s')
|
28
28
|
tra = <<-EOF
|
29
29
|
<?xml version="1.0" encoding="UTF-8"?>
|
30
30
|
<loginTicketRequest version="1.0">
|
31
31
|
<header>
|
32
|
-
<uniqueId>#{ id }</uniqueId>
|
33
|
-
<generationTime>#{ from }</generationTime>
|
34
|
-
<expirationTime>#{ to }</expirationTime>
|
32
|
+
<uniqueId>#{ @id }</uniqueId>
|
33
|
+
<generationTime>#{ @from }</generationTime>
|
34
|
+
<expirationTime>#{ @to }</expirationTime>
|
35
35
|
</header>
|
36
36
|
<service>wsfe</service>
|
37
37
|
</loginTicketRequest>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe
|
5
|
-
it
|
3
|
+
describe 'AuthData' do
|
4
|
+
describe '.fetch' do
|
5
|
+
it 'creates constants for todays data' do
|
6
6
|
Bravo.constants.should_not include(:TOKEN, :SIGN)
|
7
7
|
|
8
8
|
Bravo::AuthData.fetch
|
data/spec/bravo/bill_spec.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe 'Bill' do
|
5
5
|
let(:bill) { @bill = Bravo::Bill.new }
|
6
6
|
|
7
|
-
describe
|
8
|
-
it
|
7
|
+
describe '.header' do
|
8
|
+
it 'sets up the header hash' do
|
9
9
|
@header = Bravo::Bill.header(0)
|
10
10
|
@header.size.should == 3
|
11
|
-
[
|
11
|
+
['CantReg', 'CbteTipo', 'PtoVta'].each do |key|
|
12
12
|
@header.has_key?(key).should == true
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
describe
|
18
|
-
it
|
19
|
-
bill.client.class.name.should ==
|
17
|
+
describe '.initialize' do
|
18
|
+
it 'applies Bravos defaults' do
|
19
|
+
bill.client.class.name.should == 'Savon::Client'
|
20
20
|
|
21
|
-
[
|
22
|
-
bill.body[
|
21
|
+
['Token', 'Sign', 'Cuit'].each do |key|
|
22
|
+
bill.body['Auth'][key].should_not == nil
|
23
23
|
end
|
24
24
|
|
25
25
|
bill.documento.should == Bravo.default_documento
|
@@ -27,29 +27,29 @@ describe "Bill" do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
describe
|
30
|
+
describe '#cbte_type' do
|
31
31
|
before { bill.invoice_type = :invoice }
|
32
|
-
it
|
32
|
+
it 'returns the bill type for Responsable Inscripto' do
|
33
33
|
bill.iva_cond = :responsable_inscripto
|
34
34
|
|
35
|
-
bill.cbte_type.should ==
|
35
|
+
bill.cbte_type.should == '01'
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
38
|
+
it 'returns the bill type for Consumidor Final' do
|
39
39
|
bill.iva_cond = :consumidor_final
|
40
40
|
|
41
|
-
bill.cbte_type.should ==
|
41
|
+
bill.cbte_type.should == '06'
|
42
42
|
end
|
43
43
|
|
44
|
-
it
|
44
|
+
it 'raises error on nil or invalid iva cond' do
|
45
45
|
bill.iva_cond = 12
|
46
46
|
|
47
47
|
expect { bill.cbte_type }.to raise_error(Bravo::NullOrInvalidAttribute)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
describe
|
52
|
-
it
|
51
|
+
describe '#iva_sum and #total' do
|
52
|
+
it 'calculate the IVA array values' do
|
53
53
|
bill.iva_cond = :responsable_inscripto
|
54
54
|
bill.moneda = :peso
|
55
55
|
bill.net = 100.89
|
@@ -60,51 +60,52 @@ describe "Bill" do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
describe
|
63
|
+
describe '#setup_bill' do
|
64
64
|
before do
|
65
65
|
bill.net = 100
|
66
66
|
bill.aliciva_id = 2
|
67
|
-
bill.doc_num =
|
67
|
+
bill.doc_num = '30710151543'
|
68
68
|
bill.iva_cond = :responsable_inscripto
|
69
|
-
bill.concepto =
|
69
|
+
bill.concepto = 'Servicios'
|
70
70
|
end
|
71
71
|
|
72
|
-
it
|
72
|
+
it 'uses today dates when due and service dates are ommitted', vcr: { cassette_name: 'setup_bill_ommitted_date' } do
|
73
73
|
bill.setup_bill
|
74
74
|
|
75
|
-
detail = bill.body[
|
75
|
+
detail = bill.body['FeCAEReq']['FeDetReq']['FECAEDetRequest']
|
76
76
|
|
77
|
-
detail[
|
78
|
-
detail[
|
79
|
-
detail[
|
77
|
+
detail['FchServDesde'].should == Time.new.strftime('%Y%m%d')
|
78
|
+
detail['FchServHasta'].should == Time.new.strftime('%Y%m%d')
|
79
|
+
detail['FchVtoPago'].should == Time.new.strftime('%Y%m%d')
|
80
80
|
end
|
81
81
|
|
82
|
-
it
|
82
|
+
it 'uses given due and service dates', vcr: { cassette_name: 'setup_bill_given_date' } do
|
83
83
|
bill.due_date = Date.new(2011, 12, 10).strftime('%Y%m%d')
|
84
84
|
bill.fch_serv_desde = Date.new(2011, 11, 01).strftime('%Y%m%d')
|
85
85
|
bill.fch_serv_hasta = Date.new(2011, 11, 30).strftime('%Y%m%d')
|
86
86
|
|
87
87
|
bill.setup_bill
|
88
88
|
|
89
|
-
detail = bill.body[
|
89
|
+
detail = bill.body['FeCAEReq']['FeDetReq']['FECAEDetRequest']
|
90
90
|
|
91
|
-
detail[
|
92
|
-
detail[
|
93
|
-
detail[
|
91
|
+
detail['FchServDesde'].should == '20111101'
|
92
|
+
detail['FchServHasta'].should == '20111130'
|
93
|
+
detail['FchVtoPago'].should == '20111210'
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
describe
|
98
|
-
describe
|
97
|
+
describe '#authorize' do
|
98
|
+
describe 'for facturas' do
|
99
99
|
Bravo::BILL_TYPE[Bravo.own_iva_cond].keys.each do |target_iva_cond|
|
100
100
|
describe "issued to #{ target_iva_cond.to_s }" do
|
101
101
|
Bravo::BILL_TYPE[Bravo.own_iva_cond][target_iva_cond].keys.each do |bill_type|
|
102
|
-
|
102
|
+
vcr_options = { cassette_name: "#{ target_iva_cond.to_s }_and_#{ bill_type }" }
|
103
|
+
it "authorizes bill type #{ bill_type }", vcr: vcr_options do
|
103
104
|
bill.net = 10000.00
|
104
105
|
bill.aliciva_id = 2
|
105
|
-
bill.doc_num =
|
106
|
+
bill.doc_num = '30710151543'
|
106
107
|
bill.iva_cond = target_iva_cond
|
107
|
-
bill.concepto =
|
108
|
+
bill.concepto = 'Servicios'
|
108
109
|
bill.invoice_type = bill_type
|
109
110
|
|
110
111
|
bill.authorized?.should == false
|
@@ -121,4 +122,4 @@ describe "Bill" do
|
|
121
122
|
end
|
122
123
|
end
|
123
124
|
end
|
124
|
-
end
|
125
|
+
end
|
data/spec/bravo/wsaa_spec.rb
CHANGED
@@ -1,43 +1,39 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'Wsaa' do
|
4
4
|
before do
|
5
|
-
@
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
Time.now.should == @now
|
10
|
-
from = @now.strftime("%FT%T%:z")
|
11
|
-
to = ((@now - 120) + (24*60*60)).strftime("%FT%T%:z")
|
12
|
-
id = @now.strftime("%s")
|
5
|
+
@now = (Time.now) - 120
|
6
|
+
@from = @now.strftime('%FT%T%:z')
|
7
|
+
@to = (@now + ((12*60*60))).strftime('%FT%T%:z')
|
8
|
+
@id = @now.strftime('%s')
|
13
9
|
@tra = <<-EOF
|
14
10
|
<?xml version="1.0" encoding="UTF-8"?>
|
15
11
|
<loginTicketRequest version="1.0">
|
16
12
|
<header>
|
17
|
-
<uniqueId>#{ id }</uniqueId>
|
18
|
-
<generationTime>#{ from }</generationTime>
|
19
|
-
<expirationTime>#{ to }</expirationTime>
|
13
|
+
<uniqueId>#{ @id }</uniqueId>
|
14
|
+
<generationTime>#{ @from }</generationTime>
|
15
|
+
<expirationTime>#{ @to }</expirationTime>
|
20
16
|
</header>
|
21
17
|
<service>wsfe</service>
|
22
18
|
</loginTicketRequest>
|
23
19
|
EOF
|
24
20
|
end
|
25
21
|
|
26
|
-
describe
|
27
|
-
it
|
22
|
+
describe '.build_tra' do
|
23
|
+
it 'sets the body for the ticket request' do
|
28
24
|
Bravo::Wsaa.build_tra.should == @tra
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
32
|
-
describe
|
33
|
-
it
|
34
|
-
pending
|
28
|
+
describe '.build_cms' do
|
29
|
+
it 'returns the cms with the tra in it' do
|
30
|
+
pending 'find a proper way to stub openssl'
|
35
31
|
end
|
36
32
|
end
|
37
33
|
|
38
|
-
describe
|
39
|
-
|
34
|
+
describe '.login' do
|
35
|
+
xit 'should work', vcr: { cassette_name: 'login' } do
|
40
36
|
Bravo::Wsaa.login.should be_true
|
41
37
|
end
|
42
38
|
end
|
43
|
-
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDpjCCAo6gAwIBAgIIMKwSjJcsnxgwDQYJKoZIhvcNAQEFBQAwQzElMCMGA1UE
|
3
|
+
AwwcQUZJUCBUZXN0aW5nIENvbXB1dGFkb3JlcyBDQTENMAsGA1UECgwEQUZJUDEL
|
4
|
+
MAkGA1UEBhMCQVIwHhcNMTMwMjAxMTMwNDA4WhcNMTUxMDI5MTMwNDA4WjBEMQ0w
|
5
|
+
CwYDVQQDDARMZWFuMRkwFwYDVQQFExBDVUlUIDIwMjg3NzQwMDI3MQswCQYDVQQK
|
6
|
+
DAJObzELMAkGA1UEBhMCQVIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKQE
|
7
|
+
xPczGh5ou0LAUWa7SnScc+ojF0cDYyYXeRRNZ3r69IRjfmNjQQ9EczW+PC1h/HNv
|
8
|
+
Z2ZAu0401uO0ySAF4ncShUrwwNj4da2B9WXEcTMZ8DixApwevTQ2AKQXJ1XOzGGJ
|
9
|
+
fhyxbexDrF6EOjBno30h4NfCMQjzFqOeeXhryEwnAgMBAAGjggEfMIIBGzAMBgNV
|
10
|
+
HRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAdBgNVHQ4EFgQUfmtL+JcFml+AhNjA
|
11
|
+
X9GN4QDCAM0wHwYDVR0jBBgwFoAURHTutJwm31bhwQ3rVwuQGTY9lgEwgboGA1Ud
|
12
|
+
IASBsjCBrzCBrAYOKwYBBAGBu2MBAgECAQEwgZkwgZYGCCsGAQUFBwICMIGJHoGG
|
13
|
+
AEMAZQByAHQAaQBmAGkAYwBhAGQAbwAgAHAAYQByAGEAIABjAG8AbQBwAHUAdABh
|
14
|
+
AGQAbwByAGUAcwAgAHMAbwBsAG8AIAB2AGEAbABpAGQAbwAgAGUAbgAgAGUAbgB0
|
15
|
+
AG8AcgBuAG8AcwAgAGQAZQAgAGQAZQBzAGEAcgByAG8AbABsAG8wDQYJKoZIhvcN
|
16
|
+
AQEFBQADggEBAEW7IiTcq58vccBhfxfu2eV1UTV7/It5royRwrXwIeNqoC76KoB8
|
17
|
+
XsX3GeV+INlNyqDZ1fibfbCLsT7Vm3lkCIHX3ELKjm/hQSO/m0rIdMg4DknwsFYw
|
18
|
+
gUOjRsXAsChcCMiXgKnv080PehtvOa2AviLabp4Db6N9ghLMTT6gHkumqu8joKY5
|
19
|
+
Qkldrf+ENK5SDE+oDdU11+eMykx2rRAHg2riffUEWaPnlu+RVThsokiz3ieDqY51
|
20
|
+
i+KBfNWrnCvgh+Iz+5GosMH4neI9NXtPZo1ZrFef8aV/I/vnIBUD3/jHIUnyK62d
|
21
|
+
rPNCRze2CLIc4qT9YeUpD6NbbQ0giSPZ8Dc=
|
22
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICWwIBAAKBgQCkBMT3MxoeaLtCwFFmu0p0nHPqIxdHA2MmF3kUTWd6+vSEY35j
|
3
|
+
Y0EPRHM1vjwtYfxzb2dmQLtONNbjtMkgBeJ3EoVK8MDY+HWtgfVlxHEzGfA4sQKc
|
4
|
+
Hr00NgCkFydVzsxhiX4csW3sQ6xehDowZ6N9IeDXwjEI8xajnnl4a8hMJwIDAQAB
|
5
|
+
AoGARtN4ana6tJ7tHioF/KKryCc3NsfoaVXhHrXMJyQ1pzlvFSwRi8F0eq9IQNDh
|
6
|
+
E4fYh9B3igQx3debY8DRiO6Bl9BbWkx3ePvMr4L7e5QMR+ShhD4cqEgPCCMkWQyb
|
7
|
+
IGu5YNl6tasyHpnWaMuq5vtSiX+FFWcTGqVTzv38mlnbFmECQQDVp9Gd7sgKQnzS
|
8
|
+
vRkH+nIF1OtrAr8R3TMLhgQTw/L3nhM5XSrvyySWA8xRYqYdL8s1bR4fZvg8iFPt
|
9
|
+
QjBB6Lg1AkEAxIaJWsPVMpu7MubTtK+G7Eqx1NhBvkEC61V/sUkkwneubWfDfw9H
|
10
|
+
XwWl5mNwU7OEBifEYYuh/KhlmnXEpkvWawJAZ+y3c4DgYM0ydjdw44aYy+ljkavG
|
11
|
+
UOQtnh9UAGFB39xOMYr2BankY+v5CGVZs7y5tYUcL94gRSFy4WdendCbOQJAPR3N
|
12
|
+
x3FRcwylOd45Bl7z6bYM+bFLOLyFCOSs8lhZ2zRXBWUYkgIRYwahojVYcF9KdpOV
|
13
|
+
afR/qtA/0LpBLqo1AwJAVIZylHLqgYnRHvG3nVawMjUTB8G7FuWE/zg/OE/Cty0v
|
14
|
+
/rDWk0IBGsL7SEgOd18GJHS0JKMEuEuQ//wMLunWow==
|
15
|
+
-----END RSA PRIVATE KEY-----
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
require 'bravo'
|
3
3
|
require 'rspec'
|
4
|
+
require 'vcr'
|
5
|
+
require 'simplecov'
|
6
|
+
# SimpleCov.start
|
4
7
|
|
5
8
|
begin
|
6
9
|
require 'debugger'
|
7
10
|
rescue LoadError
|
8
11
|
end
|
9
12
|
|
13
|
+
VCR.configure do |c|
|
14
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
15
|
+
c.hook_into :fakeweb
|
16
|
+
c.configure_rspec_metadata!
|
17
|
+
end
|
10
18
|
|
11
19
|
RSpec.configure do |config|
|
12
20
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -14,21 +22,21 @@ RSpec.configure do |config|
|
|
14
22
|
config.run_all_when_everything_filtered = true
|
15
23
|
end
|
16
24
|
|
17
|
-
Bravo.pkey =
|
18
|
-
Bravo.cert =
|
19
|
-
Bravo.cuit = ENV[
|
20
|
-
Bravo.sale_point = ENV[
|
21
|
-
Bravo.default_concepto =
|
22
|
-
Bravo.default_documento =
|
25
|
+
Bravo.pkey = 'spec/fixtures/certs/pkey'
|
26
|
+
Bravo.cert = 'spec/fixtures/certs/cert.crt'
|
27
|
+
Bravo.cuit = ENV['CUIT'] || '20287740027'
|
28
|
+
Bravo.sale_point = ENV['SALE'] || '0002'
|
29
|
+
Bravo.default_concepto = 'Productos y Servicios'
|
30
|
+
Bravo.default_documento = 'CUIT'
|
23
31
|
Bravo.default_moneda = :peso
|
24
32
|
Bravo.own_iva_cond = :responsable_inscripto
|
25
|
-
Bravo.
|
26
|
-
Bravo.openssl_bin = "/usr/local/Cellar/openssl/1.0.
|
33
|
+
# Bravo.logger = { log: true, level: :critical }
|
34
|
+
Bravo.openssl_bin = ENV["TRAVIS"] ? 'openssl' : '/usr/local/Cellar/openssl/1.0.1e/bin/openssl'
|
27
35
|
Bravo::AuthData.environment = :test
|
28
36
|
|
29
37
|
# TODO: refactor into actual validations
|
30
38
|
unless Bravo.cuit
|
31
|
-
raise(Bravo::NullOrInvalidAttribute.new,
|
39
|
+
raise(Bravo::NullOrInvalidAttribute.new, 'Please set CUIT env variable.')
|
32
40
|
end
|
33
41
|
|
34
42
|
[Bravo.pkey, Bravo.cert].each do |file|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bravo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc1
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 2.
|
21
|
+
version: 2.3.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 2.
|
29
|
+
version: 2.3.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: thor
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.
|
37
|
+
version: 0.17.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 0.
|
45
|
+
version: 0.17.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: rspec
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,6 +91,54 @@ dependencies:
|
|
91
91
|
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: 10.0.3
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: vcr
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.4.0
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.4.0
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: simplecov
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.7.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.7.1
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: fakeweb
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.3.0
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 1.3.0
|
94
142
|
description: Adaptador para el Web Service de Facturacion Electrónica de AFIP
|
95
143
|
email:
|
96
144
|
- leanucci@gmail.com
|
@@ -127,8 +175,10 @@ files:
|
|
127
175
|
- spec/bravo/bill_spec.rb
|
128
176
|
- spec/bravo/reference_spec.rb
|
129
177
|
- spec/bravo/wsaa_spec.rb
|
178
|
+
- spec/fixtures/certs/cert.crt
|
179
|
+
- spec/fixtures/certs/pkey
|
130
180
|
- spec/spec_helper.rb
|
131
|
-
homepage:
|
181
|
+
homepage: https://github.com/leanucci/bravo#readme
|
132
182
|
licenses: []
|
133
183
|
post_install_message:
|
134
184
|
rdoc_options: []
|
@@ -158,5 +208,7 @@ test_files:
|
|
158
208
|
- spec/bravo/bill_spec.rb
|
159
209
|
- spec/bravo/reference_spec.rb
|
160
210
|
- spec/bravo/wsaa_spec.rb
|
211
|
+
- spec/fixtures/certs/cert.crt
|
212
|
+
- spec/fixtures/certs/pkey
|
161
213
|
- spec/spec_helper.rb
|
162
214
|
has_rdoc:
|