cfdi40 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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