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 CHANGED
@@ -25,10 +25,10 @@ tmtags
25
25
  .rspec
26
26
  log/
27
27
  log/*.log
28
- fixtures/
29
- fixtures/*
28
+ ./fixtures/
29
+ ./fixtures/vcr_cassettes/
30
30
  *.gem
31
31
  tmp/
32
32
  bin/bravo-certs/
33
33
  .ruby-version
34
- Gemfile.lock
34
+ Gemfile.lock
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
+ - 2.0.0
4
5
  bundler_args: --without test
5
6
  branches:
6
7
  only:
7
8
  - master
8
- env:
9
- - TRAVISCI = yes
data/CHANGELOG CHANGED
@@ -1,4 +1,7 @@
1
- *Bravo 1.0.0.alpha (March 30, 2013)*
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
@@ -1,6 +1,6 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- unless ENV['TRAVISCI'] == "yes"
3
+ group :test do
4
4
  gem 'guard-rspec', '~> 2.4.0'
5
5
  gem 'rb-fsevent', '~> 0.9.1'
6
6
  gem 'debugger', '~> 1.3.0'
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
- ## Instalación
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
- gem install bravo
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
- o
20
+ Como regla general, basta correr desde la línea de comandos ```openssl cms```
12
21
 
13
- gem 'bravo'
22
+ Si el comando ```cms``` no está disponible, se debe actualizar OpenSSL.
14
23
 
24
+ ### Certificados
15
25
 
16
- en tu `Gemfile`
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
- ## Comenzar a usar Bravo
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
- Los servicios de AFIP requieren la utilización del Web Service de Autorización y Autenticación [(más info)](http://www.afip.gov.ar/ws/WSAA/README.txt)
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
- Luego de cumplidos los pasos indicados en el readme, basta con configurar Bravo con la ruta a los archivos. En tu aplicación:
38
+ ### Configuración
28
39
 
29
- require 'bravo'
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
- ## Uso
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
- El uso de la gema se centra en el metodo `authorize`. Este método invoca `FECAESolicitar` y devuelve el resultado, que de ser exitoso incluye el CAE y su fecha de vencimento (ver [spec/bravo/bill_spec.rb:87](https://github.com/vurbia/Bravo/blob/master/spec/bravo/bill_spec.rb#L87)
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 "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"
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("Hecho!", :green)
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("Creando pkey", :cyan)
51
+ say('Creando pkey', :cyan)
52
52
  `#{ bin } genrsa -out #{ out_path }pkey 1024`
53
- say("Hecho!\n\n", :green)
53
+ say('Hecho!\n\n', :green)
54
54
  "#{ out_path }pkey"
55
55
  end
56
56
  end
@@ -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 = "http://github.com/leanucci/bravo"
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.1.0"])
22
- gem.add_runtime_dependency(%q<thor>, ["~> 0.16.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
- end
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
@@ -1,10 +1,10 @@
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"
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 Clas for missing or invalid certifficate
15
+ # Exception Class for missing or invalid certifficate
16
16
  #
17
17
  class MissingCertificate < StandardError; end
18
18
 
19
- autoload :Authorizer, "bravo/authorizer"
20
- autoload :AuthData, "bravo/auth_data"
21
- autoload :Bill, "bravo/bill"
22
- autoload :Constants, "bravo/constants"
23
- autoload :Wsaa, "bravo/wsaa"
24
- autoload :Reference, "bravo/reference"
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
- :verbose, :openssl_bin
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
- end
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
@@ -34,14 +34,14 @@ module Bravo
34
34
  # @return [Hash]
35
35
  #
36
36
  def auth_hash
37
- { "Token" => Bravo::TOKEN, "Sign" => Bravo::SIGN, "Cuit" => Bravo.cuit }
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 "Environment not sent to either :test or :production" unless Bravo::URLS.keys.include? environment
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 "Environment not sent to either :test or :production" unless Bravo::URLS.keys.include? environment
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
 
@@ -14,8 +14,9 @@ module Bravo
14
14
 
15
15
  def initialize(attrs = {})
16
16
  Bravo::AuthData.fetch
17
- @client = Savon.client(wsdl: Bravo::AuthData.wsfe_url, log: false)
18
- @body = { "Auth" => Bravo::AuthData.auth_hash }
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, "Own iva_cond is invalid.")
33
- target_iva = own_iva.has_key?(iva_cond) ? own_iva[iva_cond] : raise(NullOrInvalidAttribute.new, "Target iva_cond is invalid.")
34
- type = target_iva.has_key?(invoice_type) ? target_iva[invoice_type] : raise(NullOrInvalidAttribute.new, "Selected invoice_type is invalid.")
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["xmlns"] = "http://ar.gov.afip.dif.FEV1/"
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 = { "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)
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!({ "FchServDesde" => fch_serv_desde || today,
105
- "FchServHasta" => fch_serv_hasta || today,
106
- "FchVtoPago" => due_date || today })
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 == "A" && response.detail_result == "A"
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
- { "CantReg" => "1", "CbteTipo" => cbte_type, "PtoVta" => Bravo.sale_point }
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["FeCAEReq"]["FeCabReq"].underscore_keys.symbolize_keys
143
- request_detail = body["FeCAEReq"]["FeDetReq"]["FECAEDetRequest"].underscore_keys.symbolize_keys
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)["AlicIva"].underscore_keys.symbolize_keys
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("Response", *keys)).new(*values)
163
+ self.response = (defined?(Struct::Response) ? Struct::Response : Struct.new('Response', *keys)).new(*values)
164
164
  end
165
165
  end
166
166
  end
@@ -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
- "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"
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 = { "Productos"=>"01", "Servicios"=>"02", "Productos y Servicios"=>"03" }
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
- "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" }
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 => "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" } }
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 = [["03", 0], ["04", 0.105], ["05", 0.21], ["06", 0.27]]
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 => "01",
68
- :debit => "02",
69
- :credit => "03" }
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 => "06",
75
- :debit => "07",
76
- :credit => "08" }
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]` #=> "01"
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 => "https://wsaahomo.afip.gov.ar/ws/services/LoginCms",
95
- :wsfe => "https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL" },
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 => "https://wsaa.afip.gov.ar/ws/services/LoginCms",
98
- :wsfe => "https://servicios1.afip.gov.ar/wsfev1/service.asmx" } }
97
+ :production => { :wsaa => 'https://wsaa.afip.gov.ar/ws/services/LoginCms',
98
+ :wsfe => 'https://servicios1.afip.gov.ar/wsfev1/service.asmx' } }
99
99
  end
@@ -8,7 +8,7 @@ class String
8
8
  word.gsub!(/::/, '/')
9
9
  word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
10
10
  word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
11
- word.tr!("-", "_")
11
+ word.tr!('-', '_')
12
12
  word.downcase!
13
13
  word
14
14
  end
@@ -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["xmlns"] = "http://ar.gov.afip.dif.FEV1/"
12
- soap.message "Auth" => Bravo::AuthData.auth_hash, "PtoVta" => Bravo.sale_point, "CbteTipo" => cbte_type
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 "Auth" => Bravo::AuthData.auth_hash
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
- @client = Savon.client(wsdl: Bravo::AuthData.wsfe_url, log: false)
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
@@ -1,5 +1,5 @@
1
1
  module Bravo
2
2
  # Gem version
3
3
  #
4
- VERSION = "1.0.0.alpha"
5
- end
4
+ VERSION = '1.0.0.rc1'
5
+ end
@@ -17,21 +17,21 @@ module Bravo
17
17
  end
18
18
 
19
19
  protected
20
- # Builds the xml for the "Ticket de Requerimiento de Acceso"
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("%FT%T%:z")
26
- to = ((now - 120) + (24*60*60)).strftime("%FT%T%:z") # make sure ti will last for 24hs - 2 mins
27
- id = now.strftime("%s")
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 "AuthData" do
4
- describe ".fetch" do
5
- it "creates constants for todays data" do
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
@@ -1,25 +1,25 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe "Bill" do
4
+ describe 'Bill' do
5
5
  let(:bill) { @bill = Bravo::Bill.new }
6
6
 
7
- describe ".header" do
8
- it "sets up the header hash" do
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
- ["CantReg", "CbteTipo", "PtoVta"].each do |key|
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 ".initialize" do
18
- it "applies Bravo's defaults" do
19
- bill.client.class.name.should == "Savon::Client"
17
+ describe '.initialize' do
18
+ it 'applies Bravos defaults' do
19
+ bill.client.class.name.should == 'Savon::Client'
20
20
 
21
- ["Token", "Sign", "Cuit"].each do |key|
22
- bill.body["Auth"][key].should_not == nil
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 "#cbte_type" do
30
+ describe '#cbte_type' do
31
31
  before { bill.invoice_type = :invoice }
32
- it "returns the bill type for Responsable Inscripto" do
32
+ it 'returns the bill type for Responsable Inscripto' do
33
33
  bill.iva_cond = :responsable_inscripto
34
34
 
35
- bill.cbte_type.should == "01"
35
+ bill.cbte_type.should == '01'
36
36
  end
37
37
 
38
- it "returns the bill type for Consumidor Final" do
38
+ it 'returns the bill type for Consumidor Final' do
39
39
  bill.iva_cond = :consumidor_final
40
40
 
41
- bill.cbte_type.should == "06"
41
+ bill.cbte_type.should == '06'
42
42
  end
43
43
 
44
- it "raises error on nil or invalid iva cond" do
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 "#iva_sum and #total" do
52
- it "calculate the IVA array values" do
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 "#setup_bill" do
63
+ describe '#setup_bill' do
64
64
  before do
65
65
  bill.net = 100
66
66
  bill.aliciva_id = 2
67
- bill.doc_num = "30710151543"
67
+ bill.doc_num = '30710151543'
68
68
  bill.iva_cond = :responsable_inscripto
69
- bill.concepto = "Servicios"
69
+ bill.concepto = 'Servicios'
70
70
  end
71
71
 
72
- it "uses today dates when due and service dates are ommitted" do
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["FeCAEReq"]["FeDetReq"]["FECAEDetRequest"]
75
+ detail = bill.body['FeCAEReq']['FeDetReq']['FECAEDetRequest']
76
76
 
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')
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 "uses given due and service dates" do
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["FeCAEReq"]["FeDetReq"]["FECAEDetRequest"]
89
+ detail = bill.body['FeCAEReq']['FeDetReq']['FECAEDetRequest']
90
90
 
91
- detail["FchServDesde"].should == "20111101"
92
- detail["FchServHasta"].should == "20111130"
93
- detail["FchVtoPago"].should == "20111210"
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 "#authorize" do
98
- describe "for facturas" do
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
- it "authorizes bill type #{ bill_type }" do
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 = "30710151543"
106
+ bill.doc_num = '30710151543'
106
107
  bill.iva_cond = target_iva_cond
107
- bill.concepto = "Servicios"
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
@@ -1,43 +1,39 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Wssa" do
3
+ describe 'Wsaa' do
4
4
  before do
5
- @stub_now = Time.now
6
- Time.stub(:now).and_return(@stub_now)
7
-
8
- @now = Time.now
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 ".build_tra" do
27
- it "sets the body for the ticket request" do
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 ".build_cms" do
33
- it "returns the cms with the tra in it" do
34
- pending "find a proper way to stub openssl"
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 ".login" do
39
- it "should work" do
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-----
@@ -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 = "spec/fixtures/certs/pkey"
18
- Bravo.cert = "spec/fixtures/certs/cert.crt"
19
- Bravo.cuit = ENV["CUIT"] || "20287740027"
20
- Bravo.sale_point = ENV["SALE"] || "0002"
21
- Bravo.default_concepto = "Productos y Servicios"
22
- Bravo.default_documento = "CUIT"
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.verbose = "true"
26
- Bravo.openssl_bin = "/usr/local/Cellar/openssl/1.0.1c/bin/openssl"
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, "Please set CUIT env variable.")
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.alpha
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.1.0
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.1.0
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.16.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.16.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: http://github.com/leanucci/bravo
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: