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 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: