facturapi 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +1,49 @@
1
1
  module Facturapi
2
2
  module Helpers
3
+ # Corresponde a la o las lineas de descuento / recargo global de una
4
+ # Boleta Electronica, etiqueta e informacion opcional, con un maximo
5
+ # de 20
3
6
  class DscRcgGlobal
4
- attr_accessor :nro_lin_dr, :tpo_mov, :glosa_dr, :tpo_valor, :valor_dr,
5
- :ind_exe_dr
7
+ # Indica el numero secuencial de linea de descuento /
8
+ # recargo de la Boleta Electronica, el cual puede ser desde la linea 1
9
+ # hasta la linea 20
10
+ attr_accessor :nro_lin_dr
11
+
12
+ # Indica el tipo de movimiento de la linea de descuento /
13
+ # recargo, informando que tipo de aplicacion tendran los posteriores
14
+ # valores en la linea, los tipos son:
15
+ # - D: Corresponde a una DESCUENTO
16
+ # - R: Corresponde a una RECARGO
17
+ attr_accessor :tpo_mov
18
+
19
+ # Corresponde a una breve descripcion del descuento / recargo
20
+ attr_accessor :glosa_dr
21
+
22
+ # Indica el tipo de valor de la linea de descuento / recargo. El valor
23
+ # sera indicado en el campo ValorDR, los tipos son:
24
+ # - % : Corresponde a un porcentaje
25
+ # - $ : Corresponde a un valor en moneda nacional
26
+ attr_accessor :tpo_valor
27
+
28
+ # Es el valor de descuento / recargo. Su valor debe ser hasta 16 digitos y
29
+ # 2 decimales. Al ser un campo de monto, se debe indicar sin decimales y
30
+ # sin separadores de miles.
31
+ attr_accessor :valor_dr
32
+
33
+ # Indicador de exencion de un descuento / recargo, para la Boleta
34
+ # Electronica. Los indicadores son:
35
+ # - 0: Descuento / Recargo se aplica a items afectos a IVA
36
+ # - 1: Descuento / Recargo se aplica a items exentos
37
+ # - 2: Descuento / Recargo se aplica a items facturables
38
+ attr_accessor :ind_exe_dr
6
39
 
7
40
  def initialize(params = {})
8
41
  @nro_lin_dr = params[:nro_lin_dr]
9
- @tpo_mov = params[:tpo_mov]
42
+ @tpo_mov = params[:tpo_mov].to_s.upcase
10
43
  @glosa_dr = params[:glosa_dr]
11
- @tpo_valor = params[:tpo_valor]
12
- @valor_dr = params[:valor_dr]
13
- @ind_exe_dr = params[:ind_exe_dr]
44
+ @tpo_valor = /^[\$\%]$/ =~ params[:tpo_valor].to_s ? params[:tpo_valor] : '$'
45
+ @valor_dr = params[:valor_dr].to_i if params[:valor_dr]
46
+ @ind_exe_dr = /^[0-2]$/ =~ params[:ind_exe_dr].to_s ? params[:ind_exe_dr] : 0
14
47
  end
15
48
 
16
49
  def as_node
@@ -23,6 +56,14 @@ module Facturapi
23
56
  dsc_rcg_global << create_node('IndExeDR') { |n| n << ind_exe_dr }
24
57
  end
25
58
  end
59
+
60
+ def descuento?
61
+ tpo_mov == 'D'
62
+ end
63
+
64
+ def recargo?
65
+ tpo_mov == 'R'
66
+ end
26
67
  end
27
68
  end
28
69
  end
@@ -1,7 +1,7 @@
1
1
  module Facturapi
2
2
  module Helpers
3
3
  class Dte
4
- attr_accessor :encabezado, :detalle, :dsc_rcg_global, :referencia
4
+ attr_accessor :encabezado, :detalle, :dsc_rcg_global, :referencia, :id
5
5
 
6
6
  def initialize(params = {})
7
7
  @encabezado = params[:encabezado]
@@ -13,7 +13,7 @@ module Facturapi
13
13
  def detalle=(detalle)
14
14
  @detalle = @detalle.nil? ? [] : @detalle
15
15
  @detalle =
16
- if @detalle.is_a?(Array)
16
+ if detalle.is_a?(Array)
17
17
  @detalle.push(*detalle)
18
18
  else
19
19
  @detalle.push(detalle)
@@ -23,7 +23,7 @@ module Facturapi
23
23
  def dsc_rcg_global=(dsc_rcg_global)
24
24
  @dsc_rcg_global = @dsc_rcg_global.nil? ? [] : @dsc_rcg_global
25
25
  @dsc_rcg_global =
26
- if @dsc_rcg_global.is_a?(Array)
26
+ if dsc_rcg_global.is_a?(Array)
27
27
  @dsc_rcg_global.push(*dsc_rcg_global)
28
28
  else
29
29
  @dsc_rcg_global.push(dsc_rcg_global)
@@ -33,25 +33,70 @@ module Facturapi
33
33
  def referencia=(referencia)
34
34
  @referencia = @referencia.nil? ? [] : @referencia
35
35
  @referencia =
36
- if @referencia.is_a?(Array)
36
+ if referencia.is_a?(Array)
37
37
  @referencia.push(*referencia)
38
38
  else
39
39
  @referencia.push(referencia)
40
40
  end
41
41
  end
42
42
 
43
+ def totales
44
+ encabezado.totales
45
+ end
46
+
43
47
  def as_node
44
48
  doc = XML::Document.new
49
+ param = { 'ID' => id } unless id.blank?
45
50
  doc.root = create_node('DTE', version: '1.0') do |dte|
46
- dte << create_node('Documento', 'ID' => 'F100T39') do |documento|
51
+ dte << create_node('Documento', param) do |documento|
47
52
  documento << encabezado.as_node
48
53
  detalle.each { |d| documento << d.as_node }
49
- dsc_rcg_global.each { |d| documento << d.as_node }
50
- referencia.each { |r| documento << r.as_node }
54
+ dsc_rcg_global.each { |d| documento << d.as_node } if dsc_rcg_global && dsc_rcg_global.any?
55
+ referencia.each { |r| documento << r.as_node } if referencia && referencia.any?
51
56
  end
52
57
  end
53
58
  doc
54
59
  end
60
+
61
+ def autocomplete!
62
+ mnt_neto = 0
63
+ mnt_exe = 0
64
+ monto_nf = 0
65
+ detalle.each_with_index do |det, idx|
66
+ det.nro_lin_det = idx + 1 if det.nro_lin_det.blank?
67
+ det.autocomplete!
68
+ mnt_neto += det.monto_item if det.afecto_iva?
69
+ mnt_exe += det.monto_item if det.exento_iva?
70
+ monto_nf += det.monto_item if det.no_fact? || det.no_fact_neg?
71
+ end
72
+ if dsc_rcg_global && dsc_rcg_global.any?
73
+ dsc_rcg_global.each_with_index do |drg, idx|
74
+ drg.nro_lin_dr = idx + 1 if drg.nro_lin_dr.blank?
75
+ if drg.descuento?
76
+ mnt_neto -= drg.valor_dr
77
+ else
78
+ mnt_neto += drg.valor_dr
79
+ end
80
+ end
81
+ end
82
+ if referencia && referencia.any?
83
+ referencia.each_with_index do |ref, idx|
84
+ ref.nro_lin_ref = idx + 1 if ref.nro_lin_ref.blank?
85
+ end
86
+ end
87
+ totales.autocomplete!(
88
+ is_monto_neto: encabezado.id_doc.monto_neto?,
89
+ is_boleta: encabezado.id_doc.boleta?,
90
+ mnt_neto: mnt_neto,
91
+ mnt_exe: mnt_exe,
92
+ monto_nf: monto_nf
93
+ )
94
+ self
95
+ end
96
+
97
+ def to_s
98
+ as_node.to_s
99
+ end
55
100
  end
56
101
  end
57
102
  end
@@ -1,8 +1,35 @@
1
1
  module Facturapi
2
2
  module Helpers
3
+ # Corresponde a los datos del Emisor de una Boleta Electronica
3
4
  class Emisor
4
- attr_accessor :rut_emisor, :rzn_soc_emisor, :giro_emisor, :dir_origen,
5
- :cmna_origen, :ciudad_origen
5
+ # Corresponde al RUT del Emisor, con valor desde 100.000
6
+ # hasta 99 millones, guion y digito verificador (sin separador de miles).
7
+ attr_accessor :rut_emisor
8
+
9
+ # Corresponde a la razon social o nombre del contribuyente Emisor.
10
+ attr_accessor :rzn_soc_emisor
11
+
12
+ # Corresponde al giro del negocio del Emisor antes identificado.
13
+ attr_accessor :giro_emisor
14
+
15
+ # Corresponde a la direccion legal del Emisor (registrada en el SII), no
16
+ # se especifica la comuna ni la ciudad.
17
+ attr_accessor :dir_origen
18
+
19
+ # Corresponde a la comuna legal del Emisor (registrada en el SII).
20
+ attr_accessor :cmna_origen
21
+
22
+ # Corresponde a la ciudad legal del Emisor (registrada en el SII)
23
+ attr_accessor :ciudad_origen
24
+
25
+ # Indica nombre de la sucursal que emite el Documento. Corresponde a un
26
+ # dato administrado por el emisor que puede ser un texto o un numero, con
27
+ # un maximo de 20 caracteres.
28
+ attr_accessor :sucursal
29
+
30
+ # Corresponde a la Glosa con identificador del vendedor, con un maximo de
31
+ # 60 caracteres.
32
+ attr_accessor :cdg_vendedor
6
33
 
7
34
  def initialize(params = {})
8
35
  @rut_emisor = params[:rut_emisor]
@@ -11,16 +38,20 @@ module Facturapi
11
38
  @dir_origen = params[:dir_origen]
12
39
  @cmna_origen = params[:cmna_origen]
13
40
  @ciudad_origen = params[:ciudad_origen]
41
+ @sucursal = params[:sucursal]
42
+ @cdg_vendedor = params[:cdg_vendedor]
14
43
  end
15
44
 
16
45
  def as_node
17
46
  create_node('Emisor') do |emisor|
18
47
  emisor << create_node('RUTEmisor') { |n| n << rut_emisor }
19
- emisor << create_node('RznSocEmisor') { |n| n << rzn_soc_emisor }
20
- emisor << create_node('GiroEmisor') { |n| n << giro_emisor }
21
- emisor << create_node('DirOrigen') { |n| n << dir_origen }
22
- emisor << create_node('CmnaOrigen') { |n| n << cmna_origen }
23
- emisor << create_node('CiudadOrigen') { |n| n << ciudad_origen }
48
+ emisor << create_node('RznSocEmisor') { |n| n << rzn_soc_emisor } if rzn_soc_emisor
49
+ emisor << create_node('GiroEmisor') { |n| n << giro_emisor } if giro_emisor
50
+ emisor << create_node('DirOrigen') { |n| n << dir_origen } if dir_origen
51
+ emisor << create_node('CmnaOrigen') { |n| n << cmna_origen } if cmna_origen
52
+ emisor << create_node('CiudadOrigen') { |n| n << ciudad_origen } if ciudad_origen
53
+ emisor << create_node('Sucursal') { |n| n << sucursal } if sucursal
54
+ emisor << create_node('CdgVendedor') { |n| n << cdg_vendedor } if cdg_vendedor
24
55
  end
25
56
  end
26
57
  end
@@ -7,7 +7,7 @@ module Facturapi
7
7
  @id_doc = params[:id_doc]
8
8
  @emisor = params[:emisor]
9
9
  @receptor = params[:receptor]
10
- @totales = params[:totales]
10
+ @totales = params[:totales] || Totales.new
11
11
  end
12
12
 
13
13
  def as_node
@@ -1,18 +1,124 @@
1
1
  module Facturapi
2
2
  module Helpers
3
+ # Corresponde a la Identificacion del Documento en el encabezado de una
4
+ # Boleta Electronica
3
5
  class IdDoc
4
- attr_accessor :tipo_dte, :folio, :fch_emis, :ind_servicio, :ind_mnt_neto,
5
- :periodo_desde, :periodo_hasta, :fch_venc
6
+ # Corresponde al numero de Tipo de Documento codificado por el Servicio de
7
+ # Impuestos Internos (SII).
8
+ # - 30: FACTURA
9
+ # - 32: FACTURA EXENTA
10
+ # - 33: FACTURA ELECTRONICA
11
+ # - 34: FACTURA EXENTA ELECTRONICA
12
+ # - 35: BOLETA
13
+ # - 38: BOLETA EXENTA
14
+ # - 39: BOLETA ELECTRONICA
15
+ # - 40: LIQUIDACION FACTURA
16
+ # - 41: BOLETA EXENTA ELECTRONICA
17
+ # - 43: LIQUIDACION FACTURA ELECTRONICA
18
+ # - 45: FACTURA DE COMPRA
19
+ # - 46: FACTURA DE COMPRA ELECTRONICA
20
+ # - 50: GUIA DE DESPACHO
21
+ # - 52: GUIA DE DESPACHO ELECTRONICA
22
+ # - 55: NOTA DE DEBITO
23
+ # - 56: NOTA DE DEBITO ELECTRONICA
24
+ # - 60: NOTA DE CREDITO
25
+ # - 61: NOTA DE CREDITO ELECTRONICA
26
+ attr_accessor :tipo_dte
27
+
28
+ # Es el folio del documento de acuerdo con los correlativos
29
+ # autorizados por el SII y disponibles para el tipo de documento antes
30
+ # mencionado. En el caso que se requiera auto-asignacion de folio,
31
+ # entonces se debe indicar el valor 0 (cero) en este campo.
32
+ attr_accessor :folio
33
+
34
+ # Es la fecha de emision del documento en cuestion, el formato de la fecha
35
+ # es "AAAA-MM-DD' (anio, mes, dia).
36
+ attr_accessor :fch_emis
37
+
38
+ # Corresponde a la Fecha de vencimiento y es obligatoria en
39
+ # el caso de una facturacion de servicios periodicos domiciliarios, el
40
+ # formato de la fecha es "AAAA-MM-DD' (anio, mes, dia)
41
+ attr_accessor :fch_venc
42
+
43
+ # Corresponde al indicador que identifica el tipo de transaccion que se
44
+ # realiza con el documento de acuerdo a lo codificado por el SII.
45
+ # - 1: Servicios Periodicos.
46
+ # - 2: Servicios Periodicos Domiciliarios.
47
+ # - 3: Ventas y Servicios.
48
+ # - 4: Espectaculos emitida por cuenta de terceros.
49
+ attr_accessor :ind_servicio
50
+
51
+ # Este indicador se utiliza para expresar que el precio unitario y el
52
+ # valor de todas las lineas de detalles corresponden a Montos Netos, es
53
+ # decir, no incluyen el IVA. Solo se aplica para empresas que tienen
54
+ # autorizacion para emitir las boletas desglosando el IVA. No aplica en
55
+ # Boleta Exenta.
56
+ # - 0: Lineas de Detalle indicadas en Montos Brutos.
57
+ # - 2: Lineas de Detalle indicadas en Montos Netos.
58
+ attr_accessor :ind_mnt_neto
59
+
60
+ # Es el periodo desde de una facturacion de servicios
61
+ # periodicos y aplica solamente para estos casos, el formato de la fecha
62
+ # es "AAAA-MM-DD' (anio, mes, dia).
63
+ attr_accessor :periodo_desde
64
+
65
+ # Es el periodo hasta de una facturacion de servicios
66
+ # periodicos y aplica solamente para estos casos, el formato de la fecha
67
+ # es "AAAA-MM-DD' (anio, mes, dia)
68
+ attr_accessor :periodo_hasta
69
+
70
+ # Indica si las lineas de detalle, descuentos y recargos se expresan
71
+ # en montos brutos. (Solo para documentos sin impuestos adicionales).
72
+ # Solamente se acepta el valor 1 ( <MntBruto>1</MntBruto> ).
73
+ # Si no se indica, se asume los valores en montos Netos.
74
+ attr_accessor :mnt_bruto
75
+
76
+ # (Solo para Guias de despacho) Indica si el documento acompania bienes y
77
+ # el despacho es por cuenta del vendedor o del comprador.
78
+ # No se incluye si el documento no acompania bienes o se trata de una
79
+ # Factura o Nota correspondiente a la prestacion de servicios.
80
+ # Sus valores pueden ser:
81
+ #
82
+ # - 0: Sin Despacho.
83
+ # - 1: Despacho por cuenta del receptor del documento (cliente o vendedor
84
+ # en caso de Facturas de compra).
85
+ # - 2: Despacho por cuenta del emisor a instalaciones del cliente.
86
+ # - 3: Despacho por cuenta del emisor a otras instalaciones
87
+ # (Ejemplo: entrega en Obra).
88
+ attr_accessor :tipo_despacho
89
+
90
+ # (Solo para Guias de despacho) Indica si el traslado de mercaderia es por
91
+ # Venta (valor 1) o por otros motivos que no corresponden a venta
92
+ # (valores mayores a 1). Sus valores pueden ser:
93
+ #
94
+ # - 1: Operacion constituye venta.
95
+ # - 2: Ventas por efectuar.
96
+ # - 3: Consignaciones.
97
+ # - 4: Entrega gratuita.
98
+ # - 5: Traslados internos.
99
+ # - 6: Otros traslados no venta.
100
+ # - 7: Guia de devolucion.
101
+ attr_accessor :ind_traslado
6
102
 
7
103
  def initialize(params = {})
8
- @tipo_dte = params[:tipo_dte]
9
- @folio = params[:folio]
10
- @fch_emis = params[:fch_emis]
11
- @ind_servicio = params[:ind_servicio]
12
- @ind_mnt_neto = params[:ind_mnt_neto]
13
- @periodo_desde = params[:periodo_desde]
14
- @periodo_hasta = params[:periodo_hasta]
15
- @fch_venc = params[:fch_venc]
104
+ @tipo_dte = params[:tipo_dte].to_s if Facturapi::Utils::DteTypes::VALID_REGEXP =~ params[:tipo_dte].to_s
105
+ @folio = params[:folio] || 0
106
+ @fch_emis = format_date(params[:fch_emis])
107
+ @fch_venc = format_date(params[:fch_venc])
108
+
109
+ if boleta?
110
+ @ind_servicio = params[:ind_servicio].to_s if /^[1-4]$/ =~ params[:ind_servicio].to_s
111
+ @ind_mnt_neto = params[:ind_mnt_neto].to_s if /^[02]$/ =~ params[:ind_mnt_neto].to_s
112
+ @periodo_desde = format_date(params[:periodo_desde])
113
+ @periodo_hasta = format_date(params[:periodo_hasta])
114
+ end
115
+
116
+ if guia_de_despacho?
117
+ @tipo_despacho = params[:tipo_despacho].to_s if /^[0-3]$/ =~ params[:tipo_despacho].to_s
118
+ @ind_traslado = params[:ind_traslado].to_s if /^[1-7]$/ =~ params[:ind_traslado].to_s
119
+ end
120
+
121
+ @mnt_bruto = 1 if params[:mnt_bruto]
16
122
  end
17
123
 
18
124
  def as_node
@@ -20,13 +126,40 @@ module Facturapi
20
126
  id_doc << create_node('TipoDTE') { |n| n << tipo_dte }
21
127
  id_doc << create_node('Folio') { |n| n << folio }
22
128
  id_doc << create_node('FchEmis') { |n| n << fch_emis }
23
- id_doc << create_node('IndServicio') { |n| n << ind_servicio }
24
- id_doc << create_node('IndMntNeto') { |n| n << ind_mnt_neto }
25
- id_doc << create_node('PeriodoDesde') { |n| n << periodo_desde }
26
- id_doc << create_node('PeriodoHasta') { |n| n << periodo_hasta }
27
129
  id_doc << create_node('FchVenc') { |n| n << fch_venc }
130
+ if boleta?
131
+ id_doc << create_node('IndServicio') { |n| n << ind_servicio }
132
+ id_doc << create_node('IndMntNeto') { |n| n << ind_mnt_neto }
133
+ id_doc << create_node('PeriodoDesde') { |n| n << periodo_desde }
134
+ id_doc << create_node('PeriodoHasta') { |n| n << periodo_hasta }
135
+ end
136
+ if guia_de_despacho?
137
+ id_doc << create_node('TipoDespacho') { |n| n << tipo_despacho }
138
+ id_doc << create_node('IndTraslado') { |n| n << ind_traslado }
139
+ end
140
+ id_doc << create_node('MntBruto') { |n| n << mnt_bruto } if mnt_bruto
28
141
  end
29
142
  end
143
+
144
+ def format_date(date)
145
+ date.strftime('%Y-%m-%d') if date
146
+ end
147
+
148
+ def monto_bruto?
149
+ ind_mnt_neto == '0' || mnt_bruto == 1
150
+ end
151
+
152
+ def monto_neto?
153
+ ind_mnt_neto == '2' || mnt_bruto != 1
154
+ end
155
+
156
+ def boleta?
157
+ /^39|41$/ =~ tipo_dte
158
+ end
159
+
160
+ def guia_de_despacho?
161
+ /^50|52$/ =~ tipo_dte
162
+ end
30
163
  end
31
164
  end
32
165
  end
@@ -0,0 +1,10 @@
1
+ module Facturapi
2
+ module Helpers
3
+ class RecargoGlobal < DscRcgGlobal
4
+ def initialize(params = {})
5
+ params[:tpo_mov] = 'R'
6
+ super(params)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,11 +1,45 @@
1
1
  module Facturapi
2
2
  module Helpers
3
+ # Corresponde a los datos del Receptor de una Boleta Electronica.
3
4
  class Receptor
4
- attr_accessor :rut_recep, :cdg_int_recep, :rzn_soc_recep, :contacto,
5
- :dir_recep, :cmna_recep, :ciudad_recep
5
+ RUT_AUXILIAR = '66666666-6'.freeze
6
+
7
+ # Corresponde al RUT del Cliente con valor desde 100.000 hasta 99
8
+ # millones, guion y digito verificador (sin separador de miles).
9
+ # En el caso que para una Boleta Electronica se desconozcan los datos del
10
+ # cliente, el SII ha proporcionado un RUT de Cliente Auxiliar para emitir
11
+ # en estas circunstancias.
12
+ attr_accessor :rut_recep
13
+
14
+ # Corresponde a la razon social o nombre del Cliente.
15
+ attr_accessor :rzn_soc_recep
16
+
17
+ # Corresponde a la direccion de correo electronico del Cliente a la que
18
+ # sera enviado el documento electronico tras su generacion. En el caso que
19
+ # no se desee enviar por correo electronico el documento, no debe venir
20
+ # informacion en este campo.
21
+ attr_accessor :contacto
22
+
23
+ # Corresponde a la direccion legal del Cliente (registrada en el SII), no
24
+ # se especifica la comuna ni la ciudad.
25
+ attr_accessor :dir_recep
26
+
27
+ # Corresponde a la comuna legal del Cliente (registrada en el SII)
28
+ attr_accessor :cmna_recep
29
+
30
+ # Corresponde a la ciudad legal del Cliente (registrada en el SII)
31
+ attr_accessor :ciudad_recep
32
+
33
+ # Este campo es utilizado para identificar de manera adicional al cliente,
34
+ # basado en una codificacion interna.
35
+ attr_accessor :cdg_int_recep
36
+
37
+ # Corresponde al giro del negocio del Cliente antes identificado, con un
38
+ # maximo de 40 caracteres
39
+ attr_accessor :giro_recep
6
40
 
7
41
  def initialize(params = {})
8
- @rut_recep = params[:rut_recep]
42
+ @rut_recep = params[:rut_recep] || RUT_AUXILIAR
9
43
  @cdg_int_recep = params[:cdg_int_recep]
10
44
  @rzn_soc_recep = params[:rzn_soc_recep]
11
45
  @contacto = params[:contacto]
@@ -17,12 +51,13 @@ module Facturapi
17
51
  def as_node
18
52
  create_node('Receptor') do |receptor|
19
53
  receptor << create_node('RUTRecep') { |n| n << rut_recep }
20
- receptor << create_node('CdgIntRecep') { |n| n << cdg_int_recep }
21
54
  receptor << create_node('RznSocRecep') { |n| n << rzn_soc_recep }
22
55
  receptor << create_node('Contacto') { |n| n << contacto }
23
56
  receptor << create_node('DirRecep') { |n| n << dir_recep }
24
57
  receptor << create_node('CmnaRecep') { |n| n << cmna_recep }
25
58
  receptor << create_node('CiudadRecep') { |n| n << ciudad_recep }
59
+ receptor << create_node('CdgIntRecep') { |n| n << cdg_int_recep } if cdg_int_recep
60
+ receptor << create_node('GiroRecep') { |n| n << giro_recep } if giro_recep
26
61
  end
27
62
  end
28
63
  end