facturapi 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c84c8ad9f595de425766ed65c06063b58744ae60
4
- data.tar.gz: 25ffce29b83b617bfbfda57245ad1d73865fbd5a
3
+ metadata.gz: 9c4286989ee90c94066e323aecac710629cf2695
4
+ data.tar.gz: 604c064a8cdeb558f609dfa54dbdf70e7026f10c
5
5
  SHA512:
6
- metadata.gz: aff36a3dce1bb173b18fe55917acb3123cf76cddfac684e1aa603f8156c5a53463c7aa130890af68f0941ca46749e20ba556d20565b7cac7d81eeb1a18a6b58a
7
- data.tar.gz: 6b9ca89f47ffddbd389e46cbe7af3b50bf5686f627c909bafd7fae3ed0d3cd70e7fc1d0800aec8a3d62f7aae787a525c985fdb7509b7bd6668bdf77e9d41d210
6
+ metadata.gz: 30d4c5f7152e6c74d1b20484baab7f2b4d39a640f609a7ebd6533fa099552c2a1d1c877f428f9d9a1888a6302d97cdd9a4ec278814e4247f96fbdb4ebde54b85
7
+ data.tar.gz: 4ec0827f0b24fd5b15bdd0f7a9f3bfc6db211beda4149e4b358cfbd72c3578033166d116f527cb9cff4cebb6ef94b795a3b6b26446da292460a463e74db177e3
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ require "guard/rspec/dsl"
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ # RSpec files
6
+ rspec = dsl.rspec
7
+ watch(rspec.spec_helper) { rspec.spec_dir }
8
+ watch(rspec.spec_support) { rspec.spec_dir }
9
+ watch(rspec.spec_files)
10
+
11
+ # Ruby files
12
+ ruby = dsl.ruby
13
+ dsl.watch_spec_files_for(ruby.lib_files)
14
+ end
data/README.md CHANGED
@@ -1,41 +1,138 @@
1
1
  # Facturapi
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/facturapi`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Code Climate](https://codeclimate.com/github/meloncargo/facturapi/badges/gpa.svg)](https://codeclimate.com/github/meloncargo/facturapi)
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Esta gema facilita la integración con el servicio SOAP de facturacion.cl para
6
+ aplicaciones Ruby on Rails.
6
7
 
7
- ## Installation
8
+ ## Instalación
8
9
 
9
- Add this line to your application's Gemfile:
10
+ Agrega a tu Gemfile:
10
11
 
11
12
  ```ruby
12
13
  gem 'facturapi'
13
14
  ```
14
15
 
15
- And then execute:
16
+ Y luego ejecuta
16
17
 
17
18
  $ bundle
18
19
 
19
- Or install it yourself as:
20
+ ## Configuración
20
21
 
21
- $ gem install facturapi
22
+ Agrega a tu archivo `config/initializers/facturapi.rb`:
22
23
 
23
- ## Usage
24
+ ```ruby
25
+ Facturapi.configure do |config|
26
+ config.fact_rut '1-9'
27
+ config.fact_user 'usuario'
28
+ config.fact_password '12345'
29
+ config.fact_port 9350
30
+ end
31
+ ```
32
+
33
+ o también puedes definir variables de entorno en tu sistema:
34
+
35
+ ```
36
+ FACTURACION_USER=1-9
37
+ FACTURACION_RUT=usuario
38
+ FACTURACION_PASSWORD=12345
39
+ FACTURACION_PORT=9350
40
+ ```
24
41
 
25
- TODO: Write usage instructions here
42
+ ## Uso
26
43
 
27
- ## Development
44
+ Ejemplo mínimo de envío de boleta:
28
45
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+ ```ruby
47
+ include Facturapi::Helpers
48
+
49
+ detalle = [
50
+ Detalle.new(
51
+ vlr_codigo: '17409',
52
+ nmb_item: 'Reloj',
53
+ qty_item: '1',
54
+ prc_item: 20_500
55
+ )
56
+ ]
57
+
58
+ dte = Dte.new(
59
+ encabezado: Encabezado.new(
60
+ id_doc: IdDoc.new(
61
+ fch_emis: Date.new(2016, 11, 14),
62
+ ind_servicio: 3
63
+ ),
64
+ emisor: Emisor.new(
65
+ rut_emisor: '1-9',
66
+ rzn_soc_emisor: 'SUPER EMPRESA',
67
+ giro_emisor: 'VENDEMOS COSAS',
68
+ dir_origen: 'Luis Thayer Ojeda Nº1525',
69
+ cmna_origen: 'Providencia',
70
+ ciudad_origen: 'Santiago'
71
+ ),
72
+ receptor: Receptor.new(
73
+ cdg_int_recep: '1000215-220',
74
+ rzn_soc_recep: 'Juan Perez',
75
+ contacto: 'juan@perez.com',
76
+ dir_recep: 'CALLE A 50',
77
+ cmna_recep: 'SANTIAGO',
78
+ ciudad_recep: 'SANTIAGO'
79
+ )
80
+ ),
81
+ detalle: detalle
82
+ )
83
+ # Realiza cálculos automáticos de totales, ademas de rellenar datos de
84
+ dte.autocomplete!
85
+
86
+ procesar = Facturapi::Service::Procesar.new(dte)
87
+ response = procesar.send
88
+
89
+
90
+ response.valid? # true
91
+ response.error # ''
92
+ response.folio # 4666638667
93
+ response.tipo_dte # 39
94
+ response.fecha # 2017-02-20 19:01:36 -0300
95
+ puts response
96
+ # <?xml version="1.0"?>
97
+ # <WSPLANO>
98
+ # <Resultado>True</Resultado>
99
+ # <Mensaje>Proceso exitoso.</Mensaje>
100
+ # <Detalle>
101
+ # <Documento>
102
+ # <Folio>4666638667</Folio>
103
+ # <TipoDte>39</TipoDte>
104
+ # <Operacion>VENTA</Operacion>
105
+ # <Fecha>2017-02-20T19:01:36</Fecha>
106
+ # <Resultado>True</Resultado>
107
+ # </Documento>
108
+ # </Detalle>
109
+ # </WSPLANO>
110
+
111
+ ```
30
112
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
113
+ Obtención de link para descargar documento tributario
32
114
 
33
- ## Contributing
115
+ ```ruby
116
+ obtener_link = Facturapi::Services::ObtenerLink.new(folio: '123')
117
+ response = obtener_link.send
118
+
119
+ response.url # http://www.facturacion.cl/plano/descargar.php?...
120
+ ```
34
121
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/facturapi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
122
+ Mas información sobre los atributos aceptados por los helpers, revisa [la
123
+ documentación](https://github.com/meloncargo/facturapi/tree/master/lib/facturapi/helpers)
124
+ contenida en los mismos.
36
125
 
126
+ ## Why tanto spanglish?
37
127
 
38
- ## License
128
+ Ya que esta gema sería usada principalmente por desarrolladores chilenos y para
129
+ facilidad de uso, toda la documentación irá en español. Además los nombres de
130
+ clases y variables seguirán la misma nomenclatura usada en el servicio web, la
131
+ cual es en español. Todo lo que escape a el ámbito descrito, será en inglés.
39
132
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
133
+ ## Aviso Legal
41
134
 
135
+ Esta gema no está desarrollada, soportada ni avalada de ninguna manera por
136
+ Desis Ltda. y es el resultado de ingeniería inversa al servicio de integración
137
+ de facturacion.cl con fines de interoperabilidad, como lo permite la [ley chilena
138
+ 20.435, artículo 71 Ñ, sección b.](http://www.leychile.cl/Navegar?idNorma=1012827)
@@ -0,0 +1,21 @@
1
+ es:
2
+ facturapi:
3
+ dte_type:
4
+ factura: 'Factura'
5
+ factura_ex: 'Factura exenta'
6
+ factura_elec: 'Factura electrónica'
7
+ factura_ex_elec: 'Factura exenta electrónica'
8
+ boleta: 'Boleta'
9
+ boleta_ex: 'Boleta exenta'
10
+ boleta_elec: 'Boleta electrónica'
11
+ liq_factura: 'Liquidación factura'
12
+ boleta_ex_elec: 'Boleta exenta electrónica'
13
+ liq_factura_elec: 'Liquidación factura electrónica'
14
+ factura_compra: 'Factura de compra'
15
+ factura_compra_elec: 'Factura de compra electrónica'
16
+ guia_despacho: 'Guia de despacho'
17
+ guia_despacho_elec: 'Guia de despacho electrónica'
18
+ nota_deb: 'Nota de débito'
19
+ nota_deb_elec: 'Nota de débito electrónica'
20
+ nota_cred: 'Nota de crédito'
21
+ nota_cred_elec: 'Nota de crédito electrónica'
data/facturapi.gemspec CHANGED
@@ -10,8 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["alter.strife@gmail.com"]
11
11
 
12
12
  spec.summary = %q{Ruby integration with facturacion.cl service}
13
- # spec.description = %q{TODO: Write a longer description or delete this line.}
14
- # spec.homepage = ""
13
+ spec.homepage = "https://github.com/meloncargo/facturapi"
15
14
  spec.license = "MIT"
16
15
 
17
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -23,8 +22,10 @@ Gem::Specification.new do |spec|
23
22
  spec.add_runtime_dependency "savon", "~> 2.0"
24
23
  spec.add_runtime_dependency "libxml-ruby", "~> 2.0"
25
24
  spec.add_runtime_dependency "nokogiri", "~> 1.4", ">= 1.4.0"
25
+ spec.add_runtime_dependency "i18n", "~> 0.6"
26
26
 
27
- spec.add_development_dependency "bundler", "~> 1.13"
28
27
  spec.add_development_dependency "rake", "~> 10.0"
29
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "pry-byebug", "~> 3.4.0"
30
+ spec.add_development_dependency "guard-rspec", "~> 4.7.0"
30
31
  end
data/lib/facturapi.rb CHANGED
@@ -1,6 +1,8 @@
1
+ require 'facturapi/version'
1
2
  require 'facturapi/xml'
2
3
  require 'facturapi/config'
3
4
  require 'facturapi/client'
5
+
4
6
  require 'facturapi/helpers'
5
- require 'facturapi/service'
6
- require 'facturapi/version'
7
+ require 'facturapi/services'
8
+ require 'facturapi/utils'
@@ -2,26 +2,38 @@ require 'savon'
2
2
 
3
3
  module Facturapi
4
4
  class Client
5
- attr_accessor :client
6
- attr_reader :login
5
+ class << self
6
+ def call(method, params = {})
7
+ params[:login] ||= login
8
+ client.call(method, message: params)
9
+ end
7
10
 
8
- def initialize
9
- @login = {
10
- 'Usuario' => Facturapi.config.fact_user,
11
- 'Rut' => Facturapi.config.fact_rut,
12
- 'Clave' => Facturapi.config.fact_password,
13
- 'Puerto' => Facturapi.config.fact_port
14
- }
15
- @client = Savon.client(
16
- wsdl: 'http://ws1.facturacion.cl/WSDS/wsplano.asmx?wsdl'
17
- )
18
- end
11
+ def xml(method, params = {})
12
+ ops = client.operation(method)
13
+ params[:login] ||= login
14
+ Nokogiri::XML(ops.build(message: params).to_s).to_s
15
+ end
16
+
17
+ def client
18
+ @client ||= Savon.client(
19
+ wsdl: 'http://ws1.facturacion.cl/WSDS/wsplano.asmx?wsdl'
20
+ )
21
+ end
22
+
23
+ def operations
24
+ client.operations
25
+ end
26
+
27
+ private
19
28
 
20
- def call(method, params = {})
21
- params[:login] ||= login
22
- puts params
23
- response = @client.call(method, message: params)
24
- response.body[:procesar_response][:procesar_result]
29
+ def login
30
+ @login ||= {
31
+ 'Usuario' => Facturapi.config.fact_user,
32
+ 'Rut' => Facturapi.config.fact_rut,
33
+ 'Clave' => Facturapi.config.fact_password,
34
+ 'Puerto' => Facturapi.config.fact_port
35
+ }
36
+ end
25
37
  end
26
38
  end
27
39
  end
@@ -1,5 +1,7 @@
1
1
  require 'facturapi/helpers/detalle'
2
2
  require 'facturapi/helpers/dsc_rcg_global'
3
+ require 'facturapi/helpers/descuento_global'
4
+ require 'facturapi/helpers/recargo_global'
3
5
  require 'facturapi/helpers/dte'
4
6
  require 'facturapi/helpers/emisor'
5
7
  require 'facturapi/helpers/encabezado'
@@ -0,0 +1,10 @@
1
+ module Facturapi
2
+ module Helpers
3
+ class DescuentoGlobal < DscRcgGlobal
4
+ def initialize(params = {})
5
+ params[:tpo_mov] = 'D'
6
+ super(params)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,22 +1,117 @@
1
1
  module Facturapi
2
2
  module Helpers
3
+ # Corresponde a las lineas de detalle de una Boleta Electronica, con un
4
+ # minimo de 1 linea de detalle y un maximo de 1.000 lineas
3
5
  class Detalle
4
- attr_accessor :nro_lin_det, :tpo_codigo, :vlr_codigo, :ind_exe,
5
- :rut_mandante, :nmb_item, :dsc_item, :qty_item, :unmd_item,
6
- :prc_item, :monto_item
6
+ # Indica el numero secuencial de linea de detalle de la Boleta
7
+ # Electronica, el cual puede ser desde la linea 1 hasta la linea 1.000.
8
+ attr_accessor :nro_lin_det
9
+
10
+ # Es el tipo de codigo que la empresa utiliza en el producto que se esta
11
+ # indicando en la linea de detalle; si no se tiene un tipo de codigo
12
+ # definido, se puede utilizar por defecto el tipo INT1.
13
+ attr_accessor :tpo_codigo
14
+
15
+ # Es el codigo del producto, con un maximo de 35 caracteres.
16
+ attr_accessor :vlr_codigo
17
+
18
+ # Indica si el producto o servicio del item es afecto, exento o es no
19
+ # facturable, los indicadores son:
20
+ #
21
+ # - 0: afecto a IVA
22
+ # - 1: exento de IVA
23
+ # - 2: no facturable
24
+ # - 6: no facturable (negativo)
25
+ #
26
+ # En caso que sea una factura, solo es necesario si se desea indicar que
27
+ # la linea es exenta de IVA. Los valores son:
28
+ #
29
+ # - 1: No afecto o exento de IVA
30
+ # - 2: Producto o servicio no es facturable
31
+ # - 3: Garantia de deposito por envases (Cervezas, Jugos, Aguas Minerales,
32
+ # Bebidas Analcoholicas u otros autorizados por Resolucion especial)
33
+ # - 4: item No Venta. (Para facturas y guias de despacho (esta ultima con
34
+ # Indicador Tipo de Traslado de Bienes igual a 1) y este item no
35
+ # sera facturado.
36
+ # - 5: item a rebajar. Para guias de despacho NO VENTA que rebajan guia
37
+ # anterior. En el area de referencias se debe indicar la guia
38
+ # anterior.
39
+ # - 6: Producto o servicio no facturable negativo
40
+ attr_accessor :ind_exe
41
+
42
+ # Es la descripcion del producto o servicio, es decir, corresponde al
43
+ # nombre del producto o descripcion del servicio.
44
+ attr_accessor :nmb_item
45
+
46
+ # Es la cantidad del item, su valor debe ser hasta 12 digitos y 6
47
+ # decimales.
48
+ attr_accessor :qty_item
49
+
50
+ # Es el precio unitario del item, su valor debe ser hasta 16 digitos y
51
+ # 2 decimales.
52
+ attr_accessor :prc_item
53
+
54
+ # Indica el valor del item, es decir, el valor final de la linea de
55
+ # detalle. Este valor es bruto (con IVA), excepto cuando el campo
56
+ # IndMntNeto tenga el valor 2. Al ser un campo de monto, se debe
57
+ # indicar sin decimales y sin separadores de miles.
58
+ # Se calcula de la siguiente forma:
59
+ # MontoItem = PrcItem * QtyItem
60
+ attr_accessor :monto_item
61
+
62
+ # Corresponde al RUT del Mandante si la venta o servicio es por cuenta
63
+ # de otro, el cual es responsable del IVA devengado en el periodo.
64
+ # Debe contener valor desde 100.000 hasta 99 millones, guion y digito
65
+ # verificador (sin separador de miles).
66
+ attr_accessor :rut_mandante
67
+
68
+ # Es la descripcion adicional del producto o servicio antes indicado,
69
+ # con un maximo de 1.000 caracteres, en este campo se puede indicar mas
70
+ # informacion del producto o incluso una observacion en la linea de
71
+ # detalle.
72
+ attr_accessor :dsc_item
73
+
74
+ # Es la unidad de medida que se utiliza en el producto que se esta
75
+ # indicando en la linea de detalle; si no se tiene una unidad de medida
76
+ # definida, se puede utilizar por defecto la unidad de medida UN
77
+ attr_accessor :unmd_item
78
+
79
+ # Es el porcentaje de descuento del item (cuando corresponda), si el item
80
+ # no posee descuento se debe asignar 0 (cero) o no incluir el campo en el
81
+ # documento.
82
+ attr_accessor :descuento_pct
83
+
84
+ # Es el valor de descuento del item (cuando corresponda), si el item no
85
+ # posee descuento se debe asignar 0 (cero) o no incluir el campo en el
86
+ # documento.
87
+ attr_accessor :descuento_monto
88
+
89
+ # Es el porcentaje de recargo del item (cuando corresponda), si el item
90
+ # no posee recargo se debe asignar 0 (cero) o no incluir el campo en el
91
+ # documento.
92
+ attr_accessor :recargo_pct
93
+
94
+ # Es el valor de recargo del item (cuando corresponda), si el item no
95
+ # posee recargo se debe asignar 0 (cero) o no incluir el campo en el
96
+ # documento.
97
+ attr_accessor :recargo_monto
7
98
 
8
99
  def initialize(params = {})
9
100
  @nro_lin_det = params[:nro_lin_det]
10
- @tpo_codigo = params[:tpo_codigo]
101
+ @tpo_codigo = params[:tpo_codigo] || 'INT1'
11
102
  @vlr_codigo = params[:vlr_codigo]
12
- @ind_exe = params[:ind_exe]
13
- @rut_mandante = params[:rut_mandante]
103
+ @ind_exe = /^[0126]$/ =~ params[:ind_exe].to_s ? params[:ind_exe].to_s : '0'
14
104
  @nmb_item = params[:nmb_item]
15
- @dsc_item = params[:dsc_item]
16
- @qty_item = params[:qty_item]
17
- @unmd_item = params[:unmd_item]
18
- @prc_item = params[:prc_item]
105
+ @qty_item = params[:qty_item].to_f.round(6)
106
+ @prc_item = params[:prc_item].to_f.round(2)
19
107
  @monto_item = params[:monto_item]
108
+ @rut_mandante = params[:rut_mandante]
109
+ @dsc_item = params[:dsc_item]
110
+ @unmd_item = params[:unmd_item] || 'UN'
111
+ @descuento_pct = params[:descuento_pct]
112
+ @descuento_monto = params[:descuento_monto]
113
+ @recargo_pct = params[:recargo_pct]
114
+ @recargo_monto = params[:recargo_monto]
20
115
  end
21
116
 
22
117
  def as_node
@@ -25,15 +120,39 @@ module Facturapi
25
120
  detalle << create_node('TpoCodigo') { |n| n << tpo_codigo }
26
121
  detalle << create_node('VlrCodigo') { |n| n << vlr_codigo }
27
122
  detalle << create_node('IndExe') { |n| n << ind_exe }
28
- detalle << create_node('RUTMandante') { |n| n << rut_mandante }
29
123
  detalle << create_node('NmbItem') { |n| n << nmb_item }
30
- detalle << create_node('DscItem') { |n| n << dsc_item }
31
124
  detalle << create_node('QtyItem') { |n| n << qty_item }
32
- detalle << create_node('UnmdItem') { |n| n << unmd_item }
33
125
  detalle << create_node('PrcItem') { |n| n << prc_item }
34
126
  detalle << create_node('MontoItem') { |n| n << monto_item }
127
+ detalle << create_node('RUTMandante') { |n| n << rut_mandante } if rut_mandante
128
+ detalle << create_node('DscItem') { |n| n << dsc_item } if dsc_item
129
+ detalle << create_node('UnmdItem') { |n| n << unmd_item } if unmd_item
130
+ detalle << create_node('DescuentoPct') { |n| n << descuento_pct } if descuento_pct
131
+ detalle << create_node('DescuentoMonto') { |n| n << descuento_monto } if descuento_monto
132
+ detalle << create_node('RecargoPct') { |n| n << recargo_pct } if recargo_pct
133
+ detalle << create_node('RecargoMonto') { |n| n << recargo_monto } if recargo_monto
35
134
  end
36
135
  end
136
+
137
+ def autocomplete!
138
+ self.monto_item = (prc_item * qty_item).to_i if monto_item.blank?
139
+ end
140
+
141
+ def afecto_iva?
142
+ ind_exe == '0'
143
+ end
144
+
145
+ def exento_iva?
146
+ ind_exe == '1'
147
+ end
148
+
149
+ def no_fact?
150
+ ind_exe == '2'
151
+ end
152
+
153
+ def no_fact_neg?
154
+ ind_exe == '6'
155
+ end
37
156
  end
38
157
  end
39
158
  end