bravo 1.0.0.alpha → 1.0.0.rc1
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/.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 
|
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:
|