cfdi40 0.0.4 → 0.0.5

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
  SHA256:
3
- metadata.gz: c93f265a23f6c466d800ce90e2258525844b3f15451971b0140f8c2ee826d2c5
4
- data.tar.gz: 1fcd506dfa5eefbffa1fec8ad3e98543cbc0045936859ca171b42caf46ff6649
3
+ metadata.gz: d48bd150dec201d3a2b0812d49080313c5e4aec6efd836e5606e9e2edabd822f
4
+ data.tar.gz: 3f437736ebc91684c7652f217f64a0e04c9e8b18519a18a02397ab4f95ca8db9
5
5
  SHA512:
6
- metadata.gz: 8a13afec5754aeb24cf6168f66b23b658e79cb8d8cbf93c74a11bc592ae5913f77b3d6d5da45e19b69384c94a9221bb4f7b9897e0bc6672f7360b71a0538d759
7
- data.tar.gz: 473a8ce2434b628e1fb61e8342cbdcdc1972fb00350a382e5b2b113c0d16018b804cd6d05438a2b26ddb54ba121491f9df94a75f976247eea682d7fcd7e461f2
6
+ metadata.gz: 4491ff366eeb72c4c6d1792227750e5c3f333d6df52f7d974c05eff8d4d94f30a44e98dfefaf03b1aaa41a8d1407e2765a3ef026617faa071fb86049cbbec9f9
7
+ data.tar.gz: 77c1ee1687c4b13af13768afa7a5b3ee0c7ab2071a4a3ddbf45d3bedcf4a18bb2a8e56b07bdf1762d6e833c052cf77c1b3272b04a75cb3f28d2c0494b76d66af
data/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Cfdi40
2
2
 
3
+ Please see `README_es-MX.md`
4
+
3
5
  ## [Unreleased]
4
6
 
5
7
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cfdi40 (0.0.4)
4
+ cfdi40 (0.0.5)
5
5
  nokogiri (>= 1.10.10)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -12,6 +12,8 @@ TODO: Document, document, document
12
12
  ## Features
13
13
 
14
14
  * XML generation and sign.
15
+ * Node 'iedu'
16
+ * Concept is calculated from gross price or net price
15
17
 
16
18
  ## Future features
17
19
 
data/README_es-MX.md CHANGED
@@ -14,7 +14,7 @@ que esta herramienta:
14
14
  información esencial para la elaboración del CFDi.
15
15
  * Realice los cálculos complementarios como impuestos,
16
16
  totales, etcétera.
17
- * Valide el CFDi contra los CSD
17
+ * Valide el CFDi contra los XSD
18
18
  * Selle el CFDi.
19
19
 
20
20
  # Uso
@@ -55,6 +55,23 @@ que esta herramienta:
55
55
 
56
56
  # Cambios
57
57
 
58
+ # 0.0.5
59
+
60
+ * IVA tasa 0 e IVA excento. Los conceptos con iva tasa 0 deben llevar el
61
+ nodo de traslados de impuestos. Los conceptos excentos de iva no
62
+ llevan el nodo de traslado. Al agregar el concepto usar `nil` para el
63
+ IVA cuando sea excento.
64
+ * Nuevo cálculo de impuestos e importes. El PAC solo acepta 2 decimales
65
+ en los nodos de traslado. Esto puede generar discrepancias al sumar
66
+ los conceptos si no se maneja el mismo número de decimales. Solamente
67
+ el valor unitario se manejará con 6 decimales.
68
+
69
+ # 0.0.4
70
+
71
+ * Atributos 'Total' y 'Subtotal' van con 2 decimales. Aunque el anexo 20
72
+ indica que el tipo es `t_Importe` (6 decimales) el PAC acepta solo 2
73
+ decimales si el CFDi está en pesos mexicanos.
74
+
58
75
  # 0.0.3
59
76
 
60
77
  * Lee RFC en certificados de personas morales. Los certificados de
@@ -60,7 +60,7 @@ module Cfdi40
60
60
  @sat_csd ||= SatCsd.new
61
61
  @sat_csd.cert_der = cert_data
62
62
  emisor.rfc = @sat_csd.rfc
63
- emisor.nombre = @sat_csd.name
63
+ emisor.nombre ||= @sat_csd.name
64
64
  @no_certificado = @sat_csd.no_certificado
65
65
  @certificado = @sat_csd.cert64
66
66
  true
@@ -82,18 +82,42 @@ module Cfdi40
82
82
  @docxml = nil
83
83
  end
84
84
 
85
- # clave_prod_serv
86
- # no_identificacion
87
- # cantidad
88
- # clave_unidad
89
- # unidad
90
- # descripcion
91
- # valor_unitario
92
- # importe
93
- # descuento
94
- # objeto_imp
85
+ # ## Required attributes
86
+ #
87
+ # +clave_prod_serv+:: From SAT catalogue
88
+ # +clave_unidad+:: From SAT catalogue
89
+ # +cantidad+:: Must be greather than 0
90
+ # +descripcion+:: Product or service description
91
+ #
92
+ # ### Price and Taxes attributes
93
+ #
94
+ # +tasa_iva+:: Decimal between 0 and 1. Nil means exempt. Default value is 0.16
95
+ # +tasa_ieps+:: Decimal between 0 and 1. Nil means exempt. Default value is null
96
+ # +precio_bruto+:: Price before apply taxes or gross price.
97
+ # All quantities are calculated based on this price and taxes rate.
98
+ # +precio_neto+:: Precio after taxes or net price. All quantities are calculated from this prices.
99
+ # When both, +precio_neto+ and +precio_bruto+ exist, +precio_neto+ is used
100
+ #
101
+ # The most common usage requires only the net price (+precio_neto+).
102
+ #
103
+ # ## Optional attributes:
104
+ # +no_identificacion+::
105
+ # +unidad+::
106
+ # +descuento+:: PENDING
107
+ #
108
+ # ## Special attributes
109
+ #
110
+ # ### IEDU attributes
111
+ #
112
+ # IEDU node (path: cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/cfdi:ComplementoConcepto/iedu:instEducativas) is
113
+ # generated when one of +iedu_nombre_alumno+, +iedu_curp+, +iedu_nivel_educativo+ exist.
114
+ #
115
+ # +iedu_nombre_alumno+::
116
+ # +iedu_curp+::
117
+ # +iedu_nivel_educativo+::
118
+ # +iedu_aut_rvoe+::
119
+ # +iedu_rfc_pago+::
95
120
  #
96
- # TODO: Document accepted attributes and its use
97
121
  def add_concepto(attributes = {})
98
122
  concepto = Concepto.new
99
123
  concepto.parent_node = @conceptos
@@ -1,6 +1,6 @@
1
1
  # Represents node 'concepto'
2
2
  #
3
- # * Attribute +Importe+ represente gross amount. Gross amount id before taxes and the result of multiply
3
+ # * Attribute +Importe+ represente gross amount. Gross amount is before taxes and the result of multiply
4
4
  # +ValorUnitario+ by +Cantidad+
5
5
  #
6
6
  module Cfdi40
@@ -24,7 +24,7 @@ module Cfdi40
24
24
 
25
25
  def initialize
26
26
  @tasa_iva = 0.16
27
- @tasa_ieps = 0
27
+ @tasa_ieps = nil
28
28
  super
29
29
  end
30
30
 
@@ -33,6 +33,7 @@ module Cfdi40
33
33
  def calculate!
34
34
  set_defaults
35
35
  assign_objeto_imp
36
+ # TODO: accept discount
36
37
  if defined?(@precio_neto) && !@precio_neto.nil?
37
38
  calculate_from_net_price
38
39
  elsif defined?(@precio_bruto) && !@precio_bruto.nil?
@@ -61,33 +62,26 @@ module Cfdi40
61
62
 
62
63
  def calculate_from_net_price
63
64
  set_defaults
64
- @importe_neto = precio_neto * cantidad
65
- breakdown_taxes
65
+ @precio_neto = @precio_neto.round(2)
66
+ @precio_bruto = (@precio_neto / ((1 + tasa_iva.to_f) * (1 + tasa_ieps.to_f))).round(6)
67
+ calculate_taxes
66
68
  update_xml_attributes
67
69
  end
68
70
 
69
- def breakdown_taxes
70
- @base_iva = @importe_neto / (1 + tasa_iva)
71
- @iva = @importe_neto - @base_iva
72
- @base_ieps = @base_iva / (1 + tasa_ieps)
73
- @ieps = @base_iva - @base_ieps
74
- @importe_bruto = @base_ieps
75
- @precio_bruto = @importe_bruto / @cantidad
76
- end
77
-
78
71
  def calculate_from_gross_price
79
- @importe_bruto = @precio_bruto * cantidad
80
- add_taxes
72
+ @precio_bruto = @precio_bruto.round(6)
73
+ calculate_taxes
74
+ @precio_neto = (@importe_neto / cantidad).round(2)
81
75
  update_xml_attributes
82
76
  end
83
77
 
84
- def add_taxes
85
- @base_ieps = @importe_bruto
86
- @ieps = @base_ieps * tasa_ieps
87
- @base_iva = @base_ieps + @ieps
88
- @iva = @base_iva * tasa_iva
89
- @importe_neto = @base_iva + @iva
90
- @precio_neto = @importe_neto / cantidad
78
+ def calculate_taxes
79
+ @base_ieps = (@precio_bruto * cantidad).round(2)
80
+ @ieps = (@base_ieps * tasa_ieps.to_f).round(2)
81
+ @base_iva = (@base_ieps + @ieps).round(2)
82
+ @iva = (@base_iva * tasa_iva.to_f).round(2)
83
+ @importe_bruto = @base_ieps
84
+ @importe_neto = (@base_iva + @iva).round(2)
91
85
  end
92
86
 
93
87
  def update_xml_attributes
@@ -96,7 +90,7 @@ module Cfdi40
96
90
  end
97
91
 
98
92
  def add_info_to_traslado_iva
99
- return unless @iva > 0
93
+ return if @tasa_iva.nil?
100
94
 
101
95
  traslado_iva_node.importe = @iva
102
96
  traslado_iva_node.base = @base_iva
@@ -104,9 +98,13 @@ module Cfdi40
104
98
  end
105
99
 
106
100
  def assign_objeto_imp
101
+ #01 No objeto de impuesto.
102
+ #02 Sí objeto de impuesto.
103
+ #03 Sí objeto del impuesto y no obligado al desglose.
104
+
107
105
  return if objeto_impuestos == '03'
108
106
 
109
- self.objeto_impuestos = (@tasa_iva > 0 || @tasa_ieps > 0 ? '02' : '01')
107
+ self.objeto_impuestos = (!@tasa_iva.nil? || !@tasa_ieps.nil? ? '02' : '01')
110
108
  end
111
109
 
112
110
  def impuestos_node
@@ -1,7 +1,7 @@
1
1
  module Cfdi40
2
2
  class Impuestos < Node
3
- define_attribute :total_impuestos_retenidos, xml_attribute: 'TotalImpuestosRetenidos', format: :t_Importe
4
- define_attribute :total_impuestos_trasladados, xml_attribute: 'TotalImpuestosTrasladados', format: :t_Importe
3
+ define_attribute :total_impuestos_retenidos, xml_attribute: 'TotalImpuestosRetenidos', format: :t_ImporteMXN
4
+ define_attribute :total_impuestos_trasladados, xml_attribute: 'TotalImpuestosTrasladados', format: :t_ImporteMXN
5
5
 
6
6
  def traslados
7
7
  return @traslados if defined?(@traslados)
@@ -1,9 +1,9 @@
1
1
  module Cfdi40
2
2
  class Traslado < Node
3
- define_attribute :base, xml_attribute: 'Base', format: :t_Importe
3
+ define_attribute :base, xml_attribute: 'Base', format: :t_ImporteMXN
4
4
  define_attribute :impuesto, xml_attribute: 'Impuesto'
5
5
  define_attribute :tipo_factor, xml_attribute: 'TipoFactor', default: 'Tasa'
6
6
  define_attribute :tasa_o_cuota, xml_attribute: 'TasaOCuota', format: :t_Importe
7
- define_attribute :importe, xml_attribute: 'Importe', format: :t_Importe
7
+ define_attribute :importe, xml_attribute: 'Importe', format: :t_ImporteMXN
8
8
  end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cfdi40
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.5"
5
5
  end