Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 99 additions & 12 deletions lib/bravo/reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,83 @@ def initialize
@client = Savon.client(wsdl: Bravo.service_url, log: false)
end

##
# Fetches available IVA rates.
#
# @return [Array<Hash>] List of IVA rates with :id and :descripcion.
def alic_iva
response = client.call(:fe_param_get_tipos_iva, message: {"Auth" => Bravo.auth_hash})
parse_fe_param_get_tipos_iva_response(response.to_hash)
parse_result(response, :fe_param_get_tipos_iva, :iva_tipo)
end

##
# Fetches available invoice types.
#
# @return [Array<Hash>] List of invoice types with :id and :descripcion.
def tipos_cbte
response = client.call(:fe_param_get_tipos_cbte, message: {"Auth" => Bravo.auth_hash})
parse_fe_param_get_tipos_cbte_response(response.to_hash)
parse_result(response, :fe_param_get_tipos_cbte, :cbte_tipo)
end

##
# Fetches available document types.
#
# @return [Array<Hash>] List of document types with :id and :descripcion.
def tipos_doc
response = client.call(:fe_param_get_tipos_doc, message: {"Auth" => Bravo.auth_hash})
parse_result(response, :fe_param_get_tipos_doc, :doc_tipo)
end

##
# Fetches available tax types (tributos).
#
# @return [Array<Hash>] List of tax types with :id and :descripcion.
def tipos_tributos
response = client.call(:fe_param_get_tipos_tributos, message: {"Auth" => Bravo.auth_hash})
parse_result(response, :fe_param_get_tipos_tributos, :tributo_tipo)
end

##
# Fetches available currency types.
#
# @return [Array<Hash>] List of currencies with :id and :descripcion.
def tipos_monedas
response = client.call(:fe_param_get_tipos_monedas, message: {"Auth" => Bravo.auth_hash})
parse_result(response, :fe_param_get_tipos_monedas, :moneda)
end

##
# Fetches available optional field types.
#
# @return [Array<Hash>] List of optional types with :id and :descripcion.
def tipos_opcional
response = client.call(:fe_param_get_tipos_opcional, message: {"Auth" => Bravo.auth_hash})
parse_result(response, :fe_param_get_tipos_opcional, :opcional_tipo)
end

##
# Fetches configured sales points (puntos de venta).
#
# @return [Array<Hash>] List of sales points with :nro, :emision_tipo, :bloqueado, :fch_baja.
def ptos_venta
response = client.call(:fe_param_get_ptos_venta, message: {"Auth" => Bravo.auth_hash})
parse_ptos_venta(response)
end

##
# Fetches available country types.
#
# @return [Array<Hash>] List of countries with :id and :descripcion.
def tipos_paises
response = client.call(:fe_param_get_tipos_paises, message: {"Auth" => Bravo.auth_hash})
parse_result(response, :fe_param_get_tipos_paises, :pais_tipo)
end

##
# Fetches IVA receiver conditions for invoicing.
#
# @param clase_cmp [String, nil] Optional filter by invoice class (A, B, C).
# @return [Array<Hash>] List of conditions with :id, :descripcion, :clase_comprobante.
def condicion_iva_receptor(clase_cmp = nil)
body = {"Auth" => Bravo.auth_hash}
body["ClaseCmp"] = clase_cmp if clase_cmp
Expand All @@ -30,6 +97,11 @@ def condicion_iva_receptor(clase_cmp = nil)
parse_condicion_iva_receptor_response(response.to_hash)
end

##
# Fetches exchange rate for a currency.
#
# @param moneda [Symbol] Currency symbol (:peso, :dolar, :euro, etc).
# @return [Float] Exchange rate to ARS.
def exchange_rate(moneda)
return 1 if moneda == :peso

Expand All @@ -41,6 +113,12 @@ def exchange_rate(moneda)
response.to_hash[:fe_param_get_cotizacion_response][:fe_param_get_cotizacion_result][:result_get][:mon_cotiz].to_f
end

##
# Fetches the last authorized invoice number.
#
# @param cbte_tipo [String] Invoice type code.
# @param pto_vta [String, nil] Sales point number (defaults to Bravo.sale_point).
# @return [Integer] Last authorized invoice number.
def ultimo_comprobante(cbte_tipo, pto_vta = nil)
pto_vta ||= Bravo.sale_point

Expand All @@ -55,24 +133,33 @@ def ultimo_comprobante(cbte_tipo, pto_vta = nil)

private

def parse_fe_param_get_tipos_cbte_response(response_hash)
result = response_hash[:fe_param_get_tipos_cbte_response][:fe_param_get_tipos_cbte_result][:result_get][:cbte_tipo]
def parse_result(response, operation, item_key)
response_key = "#{operation}_response".to_sym
result_key = "#{operation}_result".to_sym
result = response.to_hash[response_key][result_key][:result_get][item_key]

result.map do |comprobante|
result = [result] unless result.is_a?(Array)
result.map do |item|
{
id: comprobante[:id].to_i,
descripcion: comprobante[:desc]
id: item[:id].to_i,
descripcion: item[:desc]
}
end
end

def parse_fe_param_get_tipos_iva_response(response_hash)
result = response_hash[:fe_param_get_tipos_iva_response][:fe_param_get_tipos_iva_result][:result_get][:iva_tipo]
def parse_ptos_venta(response)
result = response.to_hash[:fe_param_get_ptos_venta_response][:fe_param_get_ptos_venta_result][:result_get]
return [] unless result

ptos = result[:pto_venta]
ptos = [ptos] unless ptos.is_a?(Array)

result.map do |iva|
ptos.map do |pto|
{
id: iva[:id].to_i,
descripcion: iva[:desc]
nro: pto[:nro].to_i,
emision_tipo: pto[:emision_tipo],
bloqueado: pto[:bloqueado],
fch_baja: pto[:fch_baja]
}
end
end
Expand Down
113 changes: 113 additions & 0 deletions spec/bravo/reference_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,117 @@
result.first.should have_key(:descripcion)
end
end

describe "#tipos_doc" do
it "should return an array of document types" do
result = @reference.tipos_doc
result.should be_a(Array)
result.should_not be_empty
end

it "should return document types with expected keys" do
result = @reference.tipos_doc
result.first.should have_key(:id)
result.first.should have_key(:descripcion)
end

it "should include CUIT document type" do
result = @reference.tipos_doc
descriptions = result.map { |d| d[:descripcion] }
descriptions.any? { |d| d =~ /cuit/i }.should == true
end
end

describe "#tipos_tributos" do
it "should return an array of tax types" do
result = @reference.tipos_tributos
result.should be_a(Array)
result.should_not be_empty
end

it "should return tax types with expected keys" do
result = @reference.tipos_tributos
result.first.should have_key(:id)
result.first.should have_key(:descripcion)
end
end

describe "#tipos_monedas" do
it "should return an array of currency types" do
result = @reference.tipos_monedas
result.should be_a(Array)
result.should_not be_empty
end

it "should return currencies with expected keys" do
result = @reference.tipos_monedas
result.first.should have_key(:id)
result.first.should have_key(:descripcion)
end

it "should include peso currency" do
result = @reference.tipos_monedas
descriptions = result.map { |m| m[:descripcion] }
descriptions.any? { |d| d =~ /peso/i }.should == true
end
end

describe "#tipos_opcional" do
it "should return an array of optional types" do
result = @reference.tipos_opcional
result.should be_a(Array)
result.should_not be_empty
end

it "should return optional types with expected keys" do
result = @reference.tipos_opcional
result.first.should have_key(:id)
result.first.should have_key(:descripcion)
end
end

describe "#ptos_venta" do
it "should return an array of sales points" do
result = @reference.ptos_venta
result.should be_a(Array)
end

it "should return sales points with expected keys" do
result = @reference.ptos_venta
next if result.empty?

pto = result.first
pto.should have_key(:nro)
pto.should have_key(:emision_tipo)
pto.should have_key(:bloqueado)
pto.should have_key(:fch_baja)
end

it "should return integer nro" do
result = @reference.ptos_venta
next if result.empty?

result.first[:nro].should be_a(Integer)
end
end

describe "#tipos_paises" do
it "should return an array of country types" do
result = @reference.tipos_paises
result.should be_a(Array)
result.should_not be_empty
end

it "should return countries with expected keys" do
result = @reference.tipos_paises
result.first.should have_key(:id)
result.first.should have_key(:descripcion)
end

it "should include Argentina" do
result = @reference.tipos_paises
descriptions = result.map { |p| p[:descripcion] }
descriptions.any? { |d| d =~ /argentina/i }.should == true
end
end
end

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@
end

config.before(:each) do
unless Bravo.const_defined?(:TOKEN)
Bravo.const_set(:TOKEN, "test_token")
Bravo.const_set(:SIGN, "test_sign")
unless ENV['VCR_RECORD']
unless Bravo.const_defined?(:TOKEN)
Bravo.const_set(:TOKEN, "test_token")
Bravo.const_set(:SIGN, "test_sign")
end
allow(Bravo::AuthData).to receive(:fetch)
end
allow(Bravo::AuthData).to receive(:fetch)
end
end

Expand All @@ -47,3 +49,8 @@
Bravo.default_documento = "CUIT"
Bravo.default_moneda = :peso
Bravo.own_iva_cond = :responsable_inscripto

if ENV['VCR_RECORD']
Bravo.pkey = "spec/fixtures/pkey"
Bravo.cert = "spec/fixtures/cert.crt"
end
Loading